T-SQL - how do I get this result set - sql

how do I get the following result set...
Desc0, Desc1, ,Desc2 ,Desc3 , Desc4
ASSETS,Fixed Assets,Tangible Fixed Assets,Land and Buildings, Equipment
ASSETS,Fixed Assets,Tangible Fixed Assets,Vehicles , Null
if the source table looks like this...
Desc, type
ASSETS, 0
Fixed Assets, 1
Tangible Fixed Assets, 2
Land and Buildings, 3
Operating Equipment 4,
Vehicles, 3
I tried this...
`SELECT case when type=0 then Name else null end report_type,
case when type=1 then Name else null end account_level_1,
case when type=2 then Name else null end account_level_2,
case when type=3 then Name else null end account_level_3,
case when type=4 then Name else null end account_level_4,
case when type=5 then Name else null end account_level_5
from [dbo].[Account]`

You want a row_number() & do conditional aggregation :
select max(case when [type] = 0 then [desc] end),
max(case when [type] = 1 then [desc] end),
max(case when [type] = 2 then [desc] end),
max(case when [type] = 3 then [desc] end)
from (select a.*,
row_number() over (partition by [type] order by [desc]) as seq
from [dbo].[Account] a
) a
group by seq;

Related

Comparing 2 tables and trace the changed columns and other set to null

I have situation when comparind 2 tables. One is current data and other is a snapshot of previous the data. The result of the comparison is stored into a #temp table ( the row which was changed). After that I am comparing #temp table to the last snapshot data to trace changed columns. I need For this I did a select statement :
I am thinking to add and ROW_NUMBER() windows function and may this will solve this.
Any suggestions?
There appears to be NULL comparisons within aggregation. SQL Server's built-in aggregate functions ignore NULLs. To test for any NULL values the query checks sum(case when [ADDRESS1] is null then 1 else 0 end)=0, etc. Something like this
with nullif_cte as (
select l.[ADDRESSID],
nullif(l.[ADDRESS1], n.[ADDRESS1]) ADDRESS1,
nullif(l.[ADDRESS2], n.[ADDRESS2]) ADDRESS2,
nullif(l.[ADDRESS3], n.[ADDRESS3]) ADDRESS3,
nullif(l.[ADDRESS4], n.[ADDRESS4]) ADDRESS4,
nullif(l.[CITY], n.[CITY]) [CITY],
nullif(l.[CLIENTID], n.[CLIENTID]) [CLIENTID],
nullif(l.[COUNTRY_CODE], n.[COUNTRY_CODE]) [COUNTRY_CODE],
nullif(l.[POST_CODE], n.[POST_CODE]) [POST_CODE]
from #tempUpdatedAddress l
left join UpdatedEntityStg n ON n.[ADDRESSID] = n.[ADDRESSID])
select [ADDRESSID],
case when sum(case when [ADDRESS1] is null then 1 else 0 end)=0
then max([ADDRESS1]) else null end [ADDRESS1],
case when sum(case when [ADDRESS2] is null then 1 else 0 end)=0
then max([ADDRESS2]) else null end [ADDRESS2],
case when sum(case when [ADDRESS3] is null then 1 else 0 end)=0
then max([ADDRESS3]) else null end [ADDRESS3],
case when sum(case when [ADDRESS4] is null then 1 else 0 end)=0
then max([ADDRESS4]) else null end [ADDRESS4],
case when sum(case when [CITY] is null then 1 else 0 end)=0
then max([CITY]) else null end [CITY],
case when sum(case when [CLIENTID] is null then 1 else 0 end)=0
then max([CLIENTID]) else null end [CLIENTID],
case when sum(case when [COUNTRY_CODE] is null then 1 else 0 end)=0
then max([COUNTRY_CODE]) else null end [COUNTRY_CODE],
case when sum(case when [POST_CODE] is null then 1 else 0 end)=0
then max([POST_CODE]) else null end [POST_CODE]
from nullif_cte nc
group by [ADDRESSID];
If I understand correctly, you can use row_number() or outer apply. The latter changes the FROM clause to:
FROM #tempUpdatedAddress l OUTER APPLY
(SELECT TOP (1) n.*
FROM UpdatedEntityStg n
WHERE n.[ADDRESSID] = n.[ADDRESSID]
ORDER BY n.snapshotdate DESC
) n
Note: You don't specify how you know the ordering of the snapshots, so I invented snapshotdate for the ORDER BY. Use whatever column contains the ordering information.

Exclude Row with Same ID but Different Secondary Column Value

Im trying to exclude a record if the ID (PK) is the same but a secondary column value is different.
So in my example below, I have two different codes E03_Port and E12_PortfNotDef for a single ID, so basically, I want to exclude the E12_PortfNotDef record if E01.. through E04.. codes are triggered.
SELECT *
FROM (
SELECT ID, Code,
MAX(CASE WHEN Code = 'E01_Matured' THEN 1 Else NULL END) AS Matured,
MAX(CASE WHEN Code = 'E02_Terminated' THEN 2 Else NULL END) AS Terminated,
MAX(CASE WHEN Code = 'E03_Port' THEN '3' Else NULL END) AS Port,
MAX(CASE WHEN Code = 'E04_Swap' THEN 4 Else NULL END) AS Swap,
MAX(CASE WHEN Code = 'E12_PortfNotDef' THEN '12' Else NULL END) AS Port_Not_Def
FROM EXCLUDED
GROUP BY ID, Code
)
WHERE COALESCE(Matured, Terminated, Port, Swap Port_Not_Def) IS NOT NULL
AND ID = '120320AC'
ORDER BY ID;
Actual Results:
ID Code Matured Terminated Port Swap Port_Not_Def
120320AC E03_Port 3
120320AC E12_PortfNotDef 12
Expected Results:
ID Code Matured Terminated Port Swap Port_Not_Def
120320AC E03_Port 3
There's a trivial way might be applied by using row_number() window analytic function :
SELECT *
FROM (
SELECT ID, Code,
MAX(CASE WHEN Code = 'E01_Matured' THEN 1 Else NULL END) AS Matured,
MAX(CASE WHEN Code = 'E02_Terminated' THEN 2 Else NULL END) AS Terminated,
MAX(CASE WHEN Code = 'E03_Port' THEN '3' Else NULL END) AS Port,
MAX(CASE WHEN Code = 'E04_Swap' THEN 4 Else NULL END) AS Swap,
MAX(CASE WHEN Code = 'E12_PortfNotDef' THEN '12' Else NULL END) AS Port_Not_Def,
ROW_NUMBER() OVER (PARTITION BY Code ORDER BY ID, Code) AS RN
FROM EXCLUDED
GROUP BY ID, Code)
WHERE COALESCE(Matured, Terminated, Port, Swap Port_Not_Def) IS NOT NULL
AND ID = '120320AC'
AND RN = 1
ORDER BY ID
I ended up restricting the ID's in the FROM Clause to not show those where Code was E01-E04.

When 1 column is null make other column equal to a certain number error

I am getting an error with this line
case
when [sm] is null
then countofMk = 0
else countofmake
end as max2
Error is :
Incorrect syntax near '='
Can anyone please advise what I am doing wrong here?
Here is the same data:
CREATE TABLE Table1
(
sku varchar(50),
[gtitle] varchar(50),
[mk] varchar(50),
[md] varchar(50),
[sm] varchar(50)
);
INSERT INTO Table1 (sku, [gtitle], [mk],[md],[sm])
VALUES ('F92', 'Game1', 'b100', 'xbox', 'pilot'),
('F92', 'Game1', 'b100', 'xbox', 'ex'),
('F92', 'Game2', 'b100', 'xbox', 'null'),
('F92', 'Game2', 'b100', 'xbox', 'LLL');
------- query
WITH mixmax AS
(
SELECT
sku, [gtitle], [mk], [md], [sm],
COUNT([mk]) AS countofMk
FROM
Table1
GROUP BY
sku, mk, md, sm, gtitle
)
SELECT
*,
CASE
WHEN [sm] IS NULL
THEN countofMk = 0
ELSE countofmake
END AS max2, --- getting error here
ROW_NUMBER() OVER (PARTITION BY sku ORDER BY sku, countofMk DESC, COALESCE([md], ''), COALESCE([sm], '') ASC) AS RowNum
FROM
mixmax;
Here is the intended result: when one column is null make the other 0
sku gtitle mk md sm countofMk max2 RowNum
F92 Game1 b100 xbox ex 1 1 1
F92 Game2 b100 xbox LLL 1 1 2
F92 Game2 b100 xbox null 1 0 3
F92 Game1 b100 xbox pilot 1 1 4
You can include condition in the original query
WITH mixmax AS
(
SELECT sku
, [gtitle]
, [mk]
, [md]
, [sm]
, COUNT(CASE WHEN [sm] IS NULL THEN NULL ELSE [mk] END) as countofMk
FROM Table1
GROUP BY sku, mk ,md, sm, gtitle
)
countofMk will be 0 for group where [sm] is null
SQL Server doesn't support boolean types. I'm not sure what you intend. Perhaps:
(case when [sm] is null then 0 else countofmake end) as max2, --- getting error here
You can't set the value of two columns on the same line. You need to do it twice, once for each column...
,max2 = case when [sm] is null then countofMk else countofmake end
or maybe
,max2 = case when [sm] is null then 0 else countofmake end
Or for setting two columns
,countofMk = case when [sm] is null then 0 end
,case when [sm] is null then 0 else countofmake end as max2
EDIT
countofMk = case when [sm] is null then 0 else countofmake end

To get one record if mre than one record exists for same id ,then get only one record based on below condition

e.g. If I get 2 null data in a column for same id, then pass null.
ii) If I get 2 same not null data in a column for same id, then pass not null.
ii) If I get 1 null and 1 not null data in a column for same id, then pass not null.
ii) If I get 2 different not null data in a column for same id, then pass '?'.
Sample data
Please find the sample data in the image.
Thanks in advance.
Output obtained after new code:
Result
You can try following :
SELECT (CASE WHEN PRTY_KEY_ID_NN= 0 THEN NULL /* IF BOTH/ALL VALUES ARE NULL */)
WHEN PRTY_KEY_ID_NN <> TOTAL_COUNT THEN PRTY_KEY_ID_NN_MX
ELSE
CASE WHEN TOTAL_COUNT=PRTY_KEY_ID_NN_DIST THEN NULL /* IF BOTH HAVING DIFFERENT NOT NULL VALUE */
CASE WHEN TOTAL_COUNT<>PRTY_KEY_ID_NN_DIST THEN PRTY_KEY_ID_NN_MX
END
END)PRTY_KEY_ID_VAL,
(CASE WHEN TOTAL_ASSET_A_NN= 0 THEN NULL /* IF BOTH/ALL VALUES ARE NULL */)
WHEN TOTAL_ASSET_A_NN <> TOTAL_COUNT THEN TOTAL_ASSET_A_MX
ELSE
CASE WHEN TOTAL_COUNT=TOTAL_ASSET_A_DIST THEN NULL /* IF BOTH HAVING DIFFERENT NOT NULL VALUE */
CASE WHEN TOTAL_COUNT<>TOTAL_ASSET_A_DIST THEN TOTAL_ASSET_A_MX
END
END)TOTAL_ASSET_VAL,
(CASE WHEN DBUS_NUM_NN= 0 THEN NULL /* IF BOTH/ALL VALUES ARE NULL */)
WHEN DBUS_NUM_NN <> TOTAL_COUNT THEN DBUS_NUM_MX
ELSE
CASE WHEN TOTAL_COUNT=DBUS_NUM_DIST THEN NULL /* IF BOTH HAVING DIFFERENT NOT NULL VALUE */
CASE WHEN TOTAL_COUNT<>DBUS_NUM_DIST THEN DBUS_NUM_MX
END
END)DBUS_NUM_DIST_VAL,
(CASE WHEN BUS_NATURE_DE_NN= 0 THEN NULL /* IF BOTH/ALL VALUES ARE NULL */)
WHEN BUS_NATURE_DE_NN <> TOTAL_COUNT THEN BUS_NATURE_DE_MX
ELSE
CASE WHEN TOTAL_COUNT=BUS_NATURE_DE_DIST THEN NULL /* IF BOTH HAVING DIFFERENT NOT NULL VALUE */
CASE WHEN TOTAL_COUNT<>BUS_NATURE_DE_DIST THEN BUS_NATURE_DE_MX
END
END)BUS_NATURE_DE_VAL
FROM
(SELECT COUNT(*)TOTAL_COUNT,
SUM(CASE WHEN PRTY_KEY_ID IS NULL THEN 0 ELSE 1 END)PRTY_KEY_ID_NN,
SUM(CASE WHEN TOTAL_ASSET_A IS NULL THEN 0 ELSE 1 END)TOTAL_ASSET_A_NN,
SUM(CASE WHEN TOTAL_LIAB_A IS NULL THEN 0 ELSE 1 END)TOTAL_LIAB_A_NN,
SUM(CASE WHEN DBUS_NUM IS NULL THEN 0 ELSE 1 END)DBUS_NUM_NN,
SUM(CASE WHEN BUS_NATURE_DE IS NULL THEN 0 ELSE 1 END)BUS_NATURE_DE_NN,
MAX(PRTY_KEY_ID_NN)PRTY_KEY_ID_NN_MX,
MAX(TOTAL_ASSET_A)TOTAL_ASSET_A_MX,
MAX(TOTAL_LIAB_A)TOTAL_LIAB_A_MX,
MAX(DBUS_NUM)DBUS_NUM_MX,
MAX(BUS_NATURE_DE)BUS_NATURE_DE_MX,
COUNT(DISTINCT PRTY_KEY_ID_NN) PRTY_KEY_ID_NN_DIST,
COUNT(DISTINCT TOTAL_ASSET_A)TOTAL_ASSET_A_DIST,
COUNT(DISTINCT TOTAL_LIAB_A)TOTAL_LIAB_A_DIST,
COUNT(DISTINCT DBUS_NUM)DBUS_NUM_DIST,
COUNT(DISTINCT BUS_NATURE_DE)BUS_NATURE_DE_DIST
FROM YOUR_TABLE)
You can find out the sample data like image in below SQL.If the column data type is varchar(char) please delete the TO_CHAR expression, and replace the table name TEST_TABLE to your table's.
WITH TEST_TABLE AS (
SELECT 1056059 AS PRTY_KEY_ID, NULL AS TOT_ASSET_AM, NULL AS TOT_LIABILITIES_AM, NULL AS DBUS_NM, 'Pediatrics' AS BUS_NATURE_DE FROM DUAL
UNION ALL
SELECT 1056059 AS PRTY_KEY_ID, 5000 AS TOT_ASSET_AM, '300000' AS TOT_LIABILITIES_AM, NULL AS DBUS_NM, 'Medicine' AS BUS_NATURE_DE FROM DUAL
)
SELECT
PRTY_KEY_ID,
MIN(CASE WHEN TOT_ASSET_AM_CNT > 1 THEN '?' ELSE TO_CHAR(TOT_ASSET_AM) END) AS TOT_ASSET_AM,
MIN(CASE WHEN TOT_LIABILITIES_AM_CNT > 1 THEN '?' ELSE TO_CHAR(TOT_LIABILITIES_AM) END) AS TOT_LIABILITIES_AM,
MIN(CASE WHEN DBUS_NM_CNT > 1 THEN '?' ELSE TO_CHAR(DBUS_NM) END) AS DBUS_NM,
MIN(CASE WHEN BUS_NATURE_DE_CNT > 1 THEN '?' ELSE TO_CHAR(BUS_NATURE_DE) END) AS BUS_NATURE_DE
FROM (
SELECT
TEST_TABLE.*,
COUNT(TOT_ASSET_AM) OVER(PARTITION BY PRTY_KEY_ID) AS TOT_ASSET_AM_CNT,
COUNT(TOT_LIABILITIES_AM) OVER(PARTITION BY PRTY_KEY_ID) AS TOT_LIABILITIES_AM_CNT,
COUNT(DBUS_NM) OVER(PARTITION BY PRTY_KEY_ID) AS DBUS_NM_CNT,
COUNT(BUS_NATURE_DE) OVER(PARTITION BY PRTY_KEY_ID) AS BUS_NATURE_DE_CNT
FROM TEST_TABLE
)
GROUP BY PRTY_KEY_ID

Subqueries in MSSQL producing NULL values

I am trying to determine my store only accounts revenue from the database, to do this I need to look through all account numbers with revenue against a 'store' description who do NOT appear in a list of accounts with an 'online' description which I have tried todo in the subquery below. The query runs however it just returns NULL values in my store_only_revenue column. Any guidance on what to do from here would be appreciated. Am I approaching the problem in a good way? Or is there a better solution:
SELECT
town,
financial_pd as month,
SUM(CASE WHEN [Descr] = 'online' THEN Net_Revenue ELSE 0 END) as online_revenue,
SUM(CASE WHEN [Descr] = 'store' THEN Net_Revenue ELSE 0 END) as store_revenue,
COUNT(DISTINCT CASE WHEN [Descr] = 'online' THEN Account_Number ELSE NULL END) as online_accounts,
COUNT(DISTINCT CASE WHEN [Descr] = 'store' THEN Account_Number ELSE NULL END) as store_accounts,
(SELECT
SUM(Net_Revenue)
FROM [mydb].[dbo].[mytable]
WHERE
Descr = 'store'
AND Account_Number
NOT IN(
SELECT DISTINCT Account_Number
FROM [mydb].[dbo].[mytable]
WHERE
Descr = 'online')
) as store_only_revenue
FROM [mydb].[dbo].[mytable] as orders
WHERE
Group_name = 'T'
AND NOT
Type_name_1 = 'Electronic'
AND
Account_type <> 1
AND
Total_Value > 0
AND
(Insert_Date BETWEEN '2016-05-30' AND '2016-07-03'
OR
Insert_Date BETWEEN '2015-05-25' AND '2015-06-28')
OR
(Insert_Date BETWEEN '2016-05-30' AND '2016-07-03'
AND
Insert_Date BETWEEN '2015-05-25' AND '2015-06-28')
GROUP BY
town,
financial_pd as period
This expression is suspect:
Account_Number NOT IN (SELECT DISTINCT t.Account_Number
FROM [mydb].[dbo].mytable t
WHERE t.Descr = 'online'
)
Assuming that the syntax problems are typos (missing table name, desc is a reserved word), then this will never return true if even one Account_Number is NULL. One way to fix this is:
Account_Number NOT IN (SELECT t.Account_Number
FROM [mydb].[dbo].mytable t
WHERE t.Desc = 'online' AND t.Account_Number IS NOT NULL
)
I would use NOT EXISTS:
not exists (select 1
from [mydb].[dbo].??? x
where x.Desc = 'online' AND ??.Account_Number = x.Account_Number
)
You need to use proper table aliases for this to work. Either of these solutions may fix your problem.