Home > Enterprise >  SQL COUNT DISTINCT with CASE : How do i subquery without using exists?
SQL COUNT DISTINCT with CASE : How do i subquery without using exists?

Time:05-02

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.)

  1. I need to count the unique values of a JSON array input (Output is in XML). (done)
  2. 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":[
      {
         "Bonnr.":42200420.0,
         "Relatie":60840.0,
         "Referentie":"ZBRA6969860",
         "Datum":"2021-07-26T00:00:00",
         "Voorzien":"2022-02-08T00:00:00",
         "Lijn":5.0,
         "Barcode":"5414365359928",
         "Artikel":"12481",
         "Omschrijving":"meat! Kip & runderhuid sticks small 12,5cm - 100g - ± 9st",
         "Hoeveelheid":2880.0,
         "Prijs":0.0,
         "Korting 1":0.0,
         "Korting 2":0.0,
         "Korting 3":0.0,
         "Netto":0.0,
         "Waarde":0.0,
         "Gewicht":331.2,
         "Intrastat":23091090.0,
         "Magazijn":"Wondelgem",
         "Locatie":"3/G15A02"
      },
      {
         "Bonnr.":42200420.0,
         "Relatie":60840.0,
         "Referentie":"TCNU4221860",
         "Datum":"2021-07-26T00:00:00",
         "Voorzien":"2022-02-08T00:00:00",
         "Lijn":10.0,
         "Barcode":"5414365341183",
         "Artikel":"11953",
         "Omschrijving":"Lam & Rijst Sticks 80gr - ± 20st",
         "Hoeveelheid":1440.0,
         "Prijs":0.0,
         "Korting 1":0.0,
         "Korting 2":0.0,
         "Korting 3":0.0,
         "Netto":0.0,
         "Waarde":0.0,
         "Gewicht":135.36,
         "Intrastat":23091011.0,
         "Magazijn":"Wondelgem",
         "Locatie":"3/G20B02"
      },
      {
         "Bonnr.":42200420.0,
         "Relatie":60840.0,
         "Referentie":"FLWU4221860",
         "Datum":"2021-07-26T00:00:00",
         "Voorzien":"2022-02-08T00:00:00",
         "Lijn":15.0,
         "Barcode":"5414365357818",
         "Artikel":"12452",
         "Omschrijving":"meat! Eend jerkies 100g - ± 18st",
         "Hoeveelheid":3600.0,
         "Prijs":0.0,
         "Korting 1":0.0,
         "Korting 2":0.0,
         "Korting 3":0.0,
         "Netto":0.0,
         "Waarde":0.0,
         "Gewicht":414.0,
         "Intrastat":23091090.0,
         "Magazijn":"Wondelgem",
         "Locatie":"3/G29B02"
      },
      {
         "Bonnr.":42200420.0,
         "Relatie":60840.0,
         "Referentie":"JDCG2348657",
         "Datum":"2021-07-26T00:00:00",
         "Voorzien":"2022-02-08T00:00:00",
         "Lijn":20.0,
         "Barcode":"5414365357900",
         "Artikel":"12456",
         "Omschrijving":"meat! Kippenfilets 100g - ± 4st",
         "Hoeveelheid":2160.0,
         "Prijs":0.0,
         "Korting 1":0.0,
         "Korting 2":0.0,
         "Korting 3":0.0,
         "Netto":0.0,
         "Waarde":0.0,
         "Gewicht":241.92,
         "Intrastat":23091090.0,
         "Magazijn":"Wondelgem",
         "Locatie":"3/G30B03"
      },
      {
         "Bonnr.":42200420.0,
         "Relatie":60840.0,
         "Referentie":"TCNU4221860",
         "Datum":"2021-07-26T00:00:00",
         "Voorzien":"2022-02-08T00:00:00",
         "Lijn":25.0,
         "Barcode":"5414365357764",
         "Artikel":"12450",
         "Omschrijving":"meat! Kip & calcium benen 500g - ± 48st",
         "Hoeveelheid":1320.0,
         "Prijs":0.0,
         "Korting 1":0.0,
         "Korting 2":0.0,
         "Korting 3":0.0,
         "Netto":0.0,
         "Waarde":0.0,
         "Gewicht":792.0,
         "Intrastat":23091090.0,
         "Magazijn":"Wondelgem",
         "Locatie":"3/G29B04"
      },
      {
         "Bonnr.":42200420.0,
         "Relatie":60840.0,
         "Referentie":"TCNU4221860",
         "Datum":"2021-07-26T00:00:00",
         "Voorzien":"2022-02-08T00:00:00",
         "Lijn":30.0,
         "Barcode":"5414365358389",
         "Artikel":"12475",
         "Omschrijving":"meat! Rijst benen met kip 140g - ± 4st",
         "Hoeveelheid":960.0,
         "Prijs":0.0,
         "Korting 1":0.0,
         "Korting 2":0.0,
         "Korting 3":0.0,
         "Netto":0.0,
         "Waarde":0.0,
         "Gewicht":144.96,
         "Intrastat":23091090.0,
         "Magazijn":"Wondelgem",
         "Locatie":"5/H05A04"
      },
      {
         "Bonnr.":42200420.0,
         "Relatie":60840.0,
         "Referentie":"TCNU4221860",
         "Datum":"2021-07-26T00:00:00",
         "Voorzien":"2022-02-08T00:00:00",
         "Lijn":35.0,
         "Barcode":"5414365358419",
         "Artikel":"12476",
         "Omschrijving":"meat! Rijst benen met eend 140g - ± 4st",
         "Hoeveelheid":60.0,
         "Prijs":0.0,
         "Korting 1":0.0,
         "Korting 2":0.0,
         "Korting 3":0.0,
         "Netto":0.0,
         "Waarde":0.0,
         "Gewicht":9.66,
         "Intrastat":23091090.0,
         "Magazijn":"Wondelgem",
         "Locatie":"5/H03A01"
      },
      {
         "Bonnr.":42200420.0,
         "Relatie":60840.0,
         "Referentie":"TCNU4221860",
         "Datum":"2021-07-26T00:00:00",
         "Voorzien":"2022-02-08T00:00:00",
         "Lijn":40.0,
         "Barcode":"5414365358099",
         "Artikel":"12464",
         "Omschrijving":"meat! Kip & kabeljauw hartjes 180g - ± 170st",
         "Hoeveelheid":1280.0,
         "Prijs":0.0,
         "Korting 1":0.0,
         "Korting 2":0.0,
         "Korting 3":0.0,
         "Netto":0.0,
         "Waarde":0.0,
         "Gewicht":248.32,
         "Intrastat":23091090.0,
         "Magazijn":"Wondelgem",
         "Locatie":"3/G19A03"
      },
      {
         "Bonnr.":42200420.0,
         "Relatie":60840.0,
         "Referentie":"TCNU4221860",
         "Datum":"2021-07-26T00:00:00",
         "Voorzien":"2022-02-08T00:00:00",
         "Lijn":45.0,
         "Barcode":"5414365341275",
         "Artikel":"11956",
         "Omschrijving":"Eendenfilets 400gr - ± 80st",
         "Hoeveelheid":864.0,
         "Prijs":0.0,
         "Korting 1":0.0,
         "Korting 2":0.0,
         "Korting 3":0.0,
         "Netto":0.0,
         "Waarde":0.0,
         "Gewicht":368.928,
         "Intrastat":23091011.0,
         "Magazijn":"Wondelgem",
         "Locatie":"3/G20B03"
      },
      {
         "Bonnr.":42200420.0,
         "Relatie":60840.0,
         "Referentie":"TCNU4221860",
         "Datum":"2021-07-26T00:00:00",
         "Voorzien":"2022-02-08T00:00:00",
         "Lijn":50.0,
         "Barcode":"5414365342852",
         "Artikel":"11997",
         "Omschrijving":"KIP & RUNDERHUID BENEN MEDIUM 1000g - ± 32st",
         "Hoeveelheid":192.0,
         "Prijs":0.0,
         "Korting 1":0.0,
         "Korting 2":0.0,
         "Korting 3":0.0,
         "Netto":0.0,
         "Waarde":0.0,
         "Gewicht":198.144,
         "Intrastat":23091090.0,
         "Magazijn":"Wondelgem",
         "Locatie":"3/G16B02"
      },
      {
         "Bonnr.":42200420.0,
         "Relatie":60840.0,
         "Referentie":"TCNU4221860",
         "Datum":"2021-07-26T00:00:00",
         "Voorzien":"2022-02-08T00:00:00",
         "Lijn":55.0,
         "Barcode":"5414365363390",
         "Artikel":"12650",
         "Omschrijving":"meat! Kip & runderhuid bagels large 15-18cm - 225g/st - ± 9st",
         "Hoeveelheid":72.0,
         "Prijs":0.0,
         "Korting 1":0.0,
         "Korting 2":0.0,
         "Korting 3":0.0,
         "Netto":0.0,
         "Waarde":0.0,
         "Gewicht":162.0,
         "Intrastat":23091090.0,
         "Magazijn":"Wondelgem",
         "Locatie":"5/H01A01"
      },
      {
         "Bonnr.":42200420.0,
         "Relatie":60840.0,
         "Referentie":"TCNU4221860",
         "Datum":"2021-07-26T00:00:00",
         "Voorzien":"2022-02-08T00:00:00",
         "Lijn":60.0,
         "Barcode":"5414365341305",
         "Artikel":"11957",
         "Omschrijving":"meat! Kippenfilets 400gr - ± 15st",
         "Hoeveelheid":288.0,
         "Prijs":0.0,
         "Korting 1":0.0,
         "Korting 2":0.0,
         "Korting 3":0.0,
         "Netto":0.0,
         "Waarde":0.0,
         "Gewicht":122.976,
         "Intrastat":23091011.0,
         "Magazijn":"Wondelgem",
         "Locatie":"3/G22B03"
      }
   ]
}'

CodePudding user response:

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

db<>fiddle

As a side point, if you really wanted multiple columns from a subquery, you would need to place it in a APPLY.

CodePudding user response:

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
GO
number | 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

  • Related