'SQL COUNT DISTINCT with CASE : How do i subquery without using exists?
context: In SQL Server have a big XLSX file that i am mapping to an XML file. A column called 'referentie' gets different values each time. I need to count unique values and display a code accordingly . (Please note that is a subquery inside a bigger SELECT statement. I'm not able to add additional aggregate funcitons.)
- I need to count the unique values of a JSON array input (Output is in XML). (done)
- Display values depending on the retrieved unique count (issue)
issue : In the query you'll see i have multiple COUNT DISTINCT CASES. SQL throws error which is normal :
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
My query :
(SELECT COUNT(DISTINCT CASE WHEN Referentie > 10 THEN N'CON1' END) AS [HEADER/CHECK],
COUNT(DISTINCT CASE WHEN Referentie <= 10 AND Referentie > 29 THEN N'CON2' END) AS [HEADER/CHECK],
COUNT(DISTINCT CASE WHEN Referentie <= 30 AND Referentie >= 50 THEN N'CON3' END) AS [HEADER/CHECK],
COUNT(DISTINCT CASE WHEN Referentie <= 50 AND Referentie >= 500 THEN N'CON4' END) AS [HEADER/CHECK]
FROM OPENJSON(@Json, N'$.Blad1')
WITH (Referentie nvarchar(100) N'$.Referentie')) AS [HEADER/CHECK],
Question:
- What is the correct syntax here to make my logic work ?
JSON in file :
@Json = N'{
"Blad1":[
{
removed
}
]
}'
Solution 1:[1]
Firstly, you are being somewhat unclear about what you are trying to achieve. You say you are managing to count unique values, but not display a value dependent on that.
Your code doesn't even manage that. What it actually does is check whether Referentie is within defined numbers (which makes no sense as it's a string), then distinct over a single string. Then it returns this multiple times, once for each parameter.
Instead, you need a single COUNT (DISTINCT Referentie), which has a CASE around it checking how much it is.
There is another issue with your current code. The conditions > and < are backwards. And < 29 should probably be < 30.
SELECT
'SomeValue' AS xyz,
(
SELECT
CASE
WHEN COUNT(DISTINCT Referentie) < 10
THEN N'CON1'
WHEN COUNT(DISTINCT Referentie) >= 10 AND COUNT(DISTINCT Referentie) < 29
THEN N'CON2'
WHEN COUNT(DISTINCT Referentie) >= 30 AND COUNT(DISTINCT Referentie) <= 50
THEN N'CON3'
WHEN COUNT(DISTINCT Referentie) >= 50 AND COUNT(DISTINCT Referentie) <= 500
THEN N'CON4'
END
FROM OPENJSON(@Json, N'$.Blad1')
WITH (
Referentie nvarchar(100)
) AS j
) AS [HEADER/CHECK]
FROM (VALUES(0)) DummyTable(DummyValue) -- don't know what the rest of your query is
FOR XML PATH(N''), ROOT(N'rootElement'),TYPE
As a side point, if you really wanted multiple columns from a subquery, you would need to place it in a APPLY.
Solution 2:[2]
I've put the first query in a CTE and then your conditions in the query following but the results are probably not what you are expecting. Firstly Referentie is alpha-numerique so I have just used the numeric part, secondly only one of the values you are testing is met.
I have therefore grouped by Referntie and shown the number of duplicates to make things clearer while you are refining your query.
declare @json varchar(max); set @Json = ---- THE VALUE GIVEN IN THE QUESTION ---
WITH myJson as ( select right(Referentie,7) Referentie FROM OPENJSON(@Json, N'$.Blad1') WITH (Referentie nvarchar(100) ) AS [HEADER/CHECK] ) SELECT COUNT(*) "number", Referentie, COUNT(DISTINCT CASE WHEN Referentie > 10 THEN N'CON1' END) AS [HEADER/CHECK], COUNT(DISTINCT CASE WHEN Referentie <= 10 AND Referentie > 29 THEN N'CON2' END) AS [HEADER/CHECK], COUNT(DISTINCT CASE WHEN Referentie <= 30 AND Referentie >= 50 THEN N'CON3' END) AS [HEADER/CHECK], COUNT(DISTINCT CASE WHEN Referentie <= 50 AND Referentie >= 500 THEN N'CON4' END) AS [HEADER/CHECK] FROM myJson GROUP BY Referentie
GOnumber | Referentie | HEADER/CHECK | HEADER/CHECK | HEADER/CHECK | HEADER/CHECK -----: | :--------- | -----------: | -----------: | -----------: | -----------: 1 | 2348657 | 1 | 0 | 0 | 0 10 | 4221860 | 1 | 0 | 0 | 0 1 | 6969860 | 1 | 0 | 0 | 0
db<>fiddle here
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Charlieface |
| Solution 2 |
