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

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

Related

SQL query to find the count of non null values in each column of table?

I can find the count of non null values by typing each column name, but is there a way to write it without manually typing the column names as I have 100+ columns in my table.
select 'col1Name', count(col1Name) from table where col1Name is null
union
select 'col2Name', count(col2Name) from table where col2Name is null
union ...
select 'col20Name', count(col20Name) from table where col20Name is null
You can use a case operation here
select
sum(case when a is null then 1 else 0 end) A,
sum(case when b is null then 1 else 0 end) B,
sum(case when c is null then 1 else 0 end) C
from T

Ignore else from CASE in SQL

Is there a way to avoid the else part when CASE is used ? For example below is the case STATUS column should display only A or B and there should not any NULL
(CASE
WHEN …..
THEN 'A'
WHEN …
THEN 'B'
END) as STATUS
Something like this:
SELECT *
FROM
(
SELECT
--ORIGINAL COLUMNS / EXPRESSIONS
, (CASE
WHEN ... THEN 'A'
WHEN ... THEN 'B'
END) as STATUS
FROM ...
)
WHERE STATUS IS NOT NULL

How to aggregate unioned tables with count and dummy values?

I am counting in two tables some stuff and want one aggregated result (one row). I write this SQL for this purpose:
SELECT sum (Amount_New) Amount_New,
sum(Import_Dropout) Import_Dropout,
sum(Import)Import,
sum(Processing)Processing,
sum(Processing_Dropout)Processing_Dropout,
sum(Matching)Matching,
sum(Matching_Dropout)Matching_Dropout,
sum(Export)Export,
sum(Exported)Exported,
sum(Rejected)Rejected,
sum(AmountSubTotal)AmountSubTotal,
sum(AmountTotal)AmountTotal
FROM (
SELECT COUNT(CASE WHEN ProcessStatus='_New' THEN 1 ELSE null END) AS Amount_New,
COUNT(CASE WHEN ProcessStatus='Import_Dropout' THEN 1 ELSE null END) AS Import_Dropout,
COUNT(CASE WHEN ProcessStatus='Import' THEN 1 ELSE null END) AS Import,
COUNT(CASE WHEN ProcessStatus='Processing' THEN 1 ELSE null END) AS Processing,
COUNT(*) AS AmountTotal,
0 as Processing_Dropout,
0 as Matching,
0 as Matching_Dropout,
0 as Export,
0 as Export_Dropout,
0 as Exported,
0 as Rejected,
0 as AmountSubTotal,
0 as UnionOrder
FROM "fileimport$marketscanimportcsv"
WHERE ft_boekdat like '%2018%'
UNION
SELECT 0 AS Amount_New,
0 AS Import_Dropout,
0 AS Import,
COUNT(CASE WHEN ProcessStatus='Processing_Dropout' THEN 1 ELSE null END) AS Processing_Dropout,
COUNT(CASE WHEN ProcessStatus='Processing' THEN 1 ELSE null END) AS Processing,
COUNT(CASE WHEN ProcessStatus='Matching' THEN 1 ELSE null END) AS Matching,
COUNT(CASE WHEN ProcessStatus='Matching_Dropout' THEN 1 ELSE null END) AS Matching_Dropout,
COUNT(CASE WHEN ProcessStatus='Export' THEN 1 ELSE null END) AS Export,
COUNT(CASE WHEN ProcessStatus='Export_Dropout' THEN 1 ELSE null END) AS Export_Dropout,
COUNT(CASE WHEN ProcessStatus='Exported' THEN 1 ELSE null END) AS Exported,
COUNT(CASE WHEN ProcessStatus='Rejected' THEN 1 ELSE null END) AS Rejected,
COUNT(CASE WHEN ProcessStatus!= '_New' and ProcessStatus!= 'Import_Dropout' and ProcessStatus!= 'Import' THEN 1 ELSE null END) AS AmountSubTotal,
COUNT(*) AS AmountTotal,
1 as UnionOrder
FROM "matching$marketscanmovement"
WHERE date_part ('year', BookingDate_BA_MS)= 2018
) SK GROUP by unionorder order by unionorder asc
1) The result is 2 rows, which is not one value as total of that column.
Why is this query not summarizing the unioned same column values? How should it be written?
2) When I try sum "(Amount_New1+Amount_New2) Amount_New" (and changing the subquery column names to amount_new1 / amount_new2) it is not working neither. Why?
If you want to return a single row, conceptually representing an aggregate over the entire union table, then remove GROUP BY:
SELECT SUM(Amount_New) Amount_New,
SUM(Import_Dropout) Import_Dropout,
SUM(Import) Import,
SUM(Processing) Processing,
SUM(Processing_Dropout) Processing_Dropout,
SUM(Matching) Matching,
SUM(Matching_Dropout) Matching_Dropout,
SUM(Export) Export,
SUM(Exported) Exported,
SUM(Rejected) Rejected,
SUM(AmountSubTotal) AmountSubTotal,
SUM(AmountTotal) AmountTotal
FROM
(
-- ... your current query
) SK;
You also may want to remove the UnionOrder computed column, since there is no need to sort a single row result set.

Check all values in another column (NULL or NOT NULL ) and return unique records

As you see for cid=1 all date fields are NULL and for cid=3 all date fields are NOT NULL.
I need get unique cids with new field, if all dates are NULL then with "NULL" and if all dates are NOT NULL then with "NOT NULL".
cid - new field
1 - NULL
3 - NOT NULL
You can do this with aggregation and case:
select cid,
(case when count(datecol) = 0 then 'NULL'
when count(datecol) = count(*) then 'NOT NULL'
end) as newField
from t
group by cid
having count(datecol) in (0, count(*));
select cid, case when min(c) = 0 AND max(c) = 0 then 'null' when min(c) = 1 and max(c) = 1 then 'not null' end from (
select cid, case when dt is null then 0 else 1 end as c from your_table
) t
group by cid
having min(c) = max(c)

Count rows for two columns using two different clauses

I'm after a CTE which I want to return two columns, one with the total number of 1's and one with the total number of 0's. Currently I can get it to return one column with the total number of 1's using:
WITH getOnesAndZerosCTE
AS (
SELECT COUNT([message]) AS TotalNo1s
FROM dbo.post
WHERE dbo.checkletters([message]) = 1
--SELECT COUNT([message]) AS TotalNo0s
--FROM dbo.post
--WHERE dbo.checkletters([message]) = 0
)
SELECT * FROM getOnesAndZerosCTE;
How do I have a second column called TotalNo0s in the same CTE which I have commented in there to show what I mean.
Using conditional aggregation:
WITH getOnesAndZerosCTE AS(
SELECT
TotalNo1s = SUM(CASE WHEN dbo.checkletters([message]) = 1 THEN 1 ELSE 0 END),
TotalNo0s = SUM(CASE WHEN dbo.checkletters([message]) = 0 THEN 1 ELSE 0 END)
FROM post
)
SELECT * FROM getOnesAndZerosCTE;
For using COUNT() directly just be aware that it counts any NON-NULL values. You can omit the ELSE condition which implicitly returns NULL if not stated
SELECT
COUNT(CASE WHEN dbo.checkletters([message]) = 1 THEN 1 END) TotalNo1s
, COUNT(CASE WHEN dbo.checkletters([message]) = 0 THEN 1 END) TotalNo0s
FROM post
or, explicitly state NULL
SELECT
COUNT(CASE WHEN dbo.checkletters([message]) = 1 THEN 1 ELSE NULL END) TotalNo1s
, COUNT(CASE WHEN dbo.checkletters([message]) = 0 THEN 1 ELSE NULL END) TotalNo0s
FROM post
You can do it without CTE
select count(message) total,
dbo.checkletters(message) strLength
from post
group by dbo.checkletters(message)
having dbo.checkletters(message) in (1, 2) //All the messages with length 1 or 2