TSQL Grouping problems - tsql

I've been given a TSQL table an extract of which is below
Serial Number Code 1 Code 2 Code 3
15872 1242 NULL NULL
15872 NULL 558 222
99955 995 452 NULL
I'd like to group these four fields together to form the following output
Serial Number Code 1 Code 2 Code 3
15872 1242 558 222
99955 995 452 NULL
This looks a simple problem, but I just can't get it right. Any advice would be very much appreciated!
Kind regards,
DJ

You need to use aggregate function in conjunction with Coalesce function , something like this :
select Serial , COALESCE(SUM(code1),0),COALESCE(SUM(code2),0),COALESCE(SUM(code3),0)
from yourTable
group by Serial
This basically replaces NULL as 0 so that you can calculate SUM as intended
Hope this helps !

Oh...misread question twice, haha.
CREATE TABLE #X
(
SerialNumber INT
, Code1 INT
, Code2 INT
, Code3 INT
)
INSERT INTO #X
VALUES
(15872, 1242, NULL, NULL)
, (15872, NULL, 558, 222)
, (99955, 995, 452, NULL)
SELECT
[SerialNumber]
, MAX([Code1]) AS [Code1]
, MAX([Code2]) AS [Code2]
, MAX([Code3]) AS [Code3]
FROM #x
GROUP BY [SerialNumber]
Now, you've not mentioned anything about an aggregate so this assumes that there is only one row that can possibly have the value i.e. this doesn't exist:
Serial Number Code 1 Code 2 Code 3
15872 1242 773 NULL
15872 NULL 558 222

Related

Select row with one column for each row in another select

An existing query returns the following table:
UserID
Sector
Value
1
1
111
1
2
122
1
3
133
2
2
222
2
3
233
3
1
311
But I would like to "reformat" it in the following way:
UserID
Sector 1
Sector 2
Sector 3
1
111
122
122
2
222
233
3
311
The maximum number of sectors is variable. Since i am new to SQL I am not sure weather this would be something DB Type Specific, so a solution which works for PostgreSQL is appreciated.
If this is something which should not be done in the database, it is also okay. I am still figuring out what to do in the database and what not.
Title is not good, I know. Please make some recommendation if you have an more precise one.
Unfortunately you cannot have dynamic number of columns.
Here is the SQL for the sample data you've provided. You must have tablefunc extension installed.
SELECT *
FROM crosstab(
'select userid, sector, value
from user_sector
order by 1,2')
AS ct(userid int, sector1 int, sector2 int,sector3 int);

Postgres NOT IN does not work as expected

I am trying to add the below condition in my query to filter data.
SELECT *
FROM dump
WHERE letpos NOT IN ('0', '(!)','NA','N/A') ;
I need only records with id 1,2,3 and 6. But the query does not return ids 3 and 6. I get only 1,2.
TABLE:
id
name
letpos
num
1
AAA
A
60
2
BBB
B
3
CCC
50
4
DDD
0
5
EEE
(!)
70
6
FFF
70
I am not sure what is missing? Could anyone advise on how to resolve this?
-Thanks
In the row with id = 3 the value of letpos is (I suspect) NULL, so the boolean expression in the WHERE clause is:
WHERE NULL NOT IN ('0', '(!)','NA','N/A');
The comparison of NULL with operators like IN, NOT IN, =, > etc always returns NULL and is never TRUE.
So you don't get this row in the results.
Check for NULL also in the WHERE clause:
SELECT *
FROM dump
WHERE letpos IS NULL
OR letpos NOT IN ('0', '(!)', 'NA', 'N/A');

Type bigint but expression is of type character varying

I'm hoping someone can lend a hand with this:
Trying to insert one row per order_id in a database that is running in RedShift, and sometimes subscription_id contains more than 1 value. This creates duplicate rows, so I figured I would LISTAGG. This is the line:
LISTAGG(DISTINCT CAST(script.subscription_id AS VARCHAR), ',') AS subscription_id
The subscription_id column is an int8 and after giving me the character varying error, I tried to CAST; but for some reason I cannot do it. Does LISTAGG do not support this type of nested CAST? If not, is there a wasy to actually achieve this?
ORIGINAL:
order_id subscription_id
1 123
2 124
3 125
1 126
2 127
IDEAL:
order_id subscription_id
1 123,126
2 124,127
3 125
Both columns are of int8.

TSQL, Pivot rows into single columns

Before, I had to solve something similar:
Here was my pivot and flatten for another solution:
I want to do the same thing on the example below but it is slightly different because there are no ranks.
In my previous example, the table looked like this:
LocationID Code Rank
1 123 1
1 124 2
1 138 3
2 999 1
2 888 2
2 938 3
And I was able to use this function to properly get my rows in a single column.
-- Check if tables exist, delete if they do so that you can start fresh.
IF OBJECT_ID('tempdb.dbo.#tbl_Location_Taxonomy_Pivot_Table', 'U') IS NOT NULL
DROP TABLE #tbl_Location_Taxonomy_Pivot_Table;
IF OBJECT_ID('tbl_Location_Taxonomy_NPPES_Flattened', 'U') IS NOT NULL
DROP TABLE tbl_Location_Taxonomy_NPPES_Flattened;
-- Pivot the original table so that you have
SELECT *
INTO #tbl_Location_Taxonomy_Pivot_Table
FROM [MOAD].[dbo].[tbl_Location_Taxonomy_NPPES] tax
PIVOT (MAX(tax.tbl_lkp_Taxonomy_Seq)
FOR tax.Taxonomy_Rank in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15])) AS pvt
-- ORDER BY Location_ID
-- Flatten the tables.
SELECT Location_ID
,max(piv.[1]) as Tax_Seq_1
,max(piv.[2]) as Tax_Seq_2
,max(piv.[3]) as Tax_Seq_3
,max(piv.[4]) as Tax_Seq_4
,max(piv.[5]) as Tax_Seq_5
,max(piv.[6]) as Tax_Seq_6
,max(piv.[7]) as Tax_Seq_7
,max(piv.[8]) as Tax_Seq_8
,max(piv.[9]) as Tax_Seq_9
,max(piv.[10]) as Tax_Seq_10
,max(piv.[11]) as Tax_Seq_11
,max(piv.[12]) as Tax_Seq_12
,max(piv.[13]) as Tax_Seq_13
,max(piv.[14]) as Tax_Seq_14
,max(piv.[15]) as Tax_Seq_15
-- JOIN HERE
INTO tbl_Location_Taxonomy_NPPES_Flattened
FROM #tbl_Location_Taxonomy_Pivot_Table piv
GROUP BY Location_ID
So, then here is the data I would like to work with in this example.
LocationID Foreign Key
2 2
2 670
2 2902
2 5389
3 3
3 722
3 2905
3 5561
So I have some data that is formatted like this:
I have used pivot on data like this before--But the difference was it had a rank also. Is there a way to get my foreign keys to show up in this format using a pivot?
locationID FK1 FK2 FK3 FK4
2 2 670 2902 5389
3 3 722 2905 5561
Another way I'm looking to solve this is like this:
Another way I could look at doing this is I have the values in:
this form as well:
LocationID Address_Seq
2 670, 5389, 2902, 2,
3 722, 5561, 2905, 3
etc
is there anyway I can get this to be the same?
ID Col1 Col2 Col3 Col4
2 670 5389, 2902, 2
This, adding a rank column and reversing the orders, should gives you what you require:
SELECT locationid, [4] col1, [3] col2, [2] col3, [1] col4
FROM
(
SELECT locationid, foreignkey,rank from #Pivot_Table ----- temp table with a rank column
) x
PIVOT (MAX(x.foreignkey)
FOR x.rank in ([4],[3],[2],[1]) ) pvt

sql - Postgresql, increment column based on other column values

I have table like
create table test(employee integer NOT NULL, code character varying(200), number integer)
I want to auto increment column 'number' on every insert record
insert into test(employee, code) values(17,'bangalore')
insert into test(employee, code) values(17,'bangalore')
insert into test(employee, code) values(17,'mumbai')
I want result like
employee code number
17 bangalore 1
17 bangalore 2
17 bangalore 3
17 mumbai 1
17 mumbai 2
17 bangalore 4
17 mumbai 3
18 bangalore 1
18 bangalore 2
18 mumbai 1
18 mumbai 2
For a batch upload of data, try if below approach would be useful.
create a temporary table test2
create table test2(employee integer NOT NULL, code character varying(200))
insert into test2(employee, code) values(17,'bangalore')
insert into test2(employee, code) values(17,'bangalore')
insert into test2(employee, code) values(17,'mumbai')
Insert into actual table along with incremental number
insert into test(employee, code, number)
select employee, code, row_number() over (partition by code ) from test2
You could include order by clause like primary key column or another column like created_date :
over (partition by code order by created_date)
create table test (employee integer NOT NULL, code character varying(200), number integer)
insert into test(employee, code, number ) values(17,'bangalore',(select coalesce(max(number) + 1,1) from test where employee = 17 and code = 'bangalore'));
insert into test(employee, code, number ) values(17,'bangalore',(select coalesce(max(number) + 1,1) from test where employee = 17 and code = 'bangalore'));
insert into test(employee, code, number ) values(17,'mumbai',(select coalesce(max(number) + 1,1) from test where employee = 17 and code = 'mumbai'));