2010-11-03 4 views
5

Grundsätzlich versuche ich eine deutliche Anzahl innerhalb dieses gewürfelten Ergebnisses zu bekommen. Aber unglücklicherweise können Sie nicht zählen (distinct (Field)) mit Cube und Rollup (as stated here)SQL Server Getting Distinct Anzahl mit "Gruppieren nach ... Mit Cube"

Hier ist, wie die Daten aussieht. (Dies ist nur ein einfaches Beispiel, das ich Duplikate tun erwarten in der Data)

Category1  Category2  ItemId 
    a    b    1 
    a    b    1 
    a    a    1 
    a    a    2 
    a    c    1 
    a    b    2 
    a    b    3 
    a    c    2 
    a    a    1 
    a    a    3 
    a    c    4 

Hier ist, was ich tun möchte, aber es funktioniert nicht.

SELECT 
    Category1, 
    Category2, 
    Count(Distinct(ItemId)) 
FROM ItemList IL 
GROUP BY 
    Category1, 
    Category2 
WITH CUBE 

Ich weiß, dass ich so ein Unter wählen tun können, um die Ergebnisse zu erhalten, ich will:

SELECT 
    *, 
    (SELECT 
    Count(Distinct(ItemId)) 
    FROM ItemList IL2 
    WHERE 
    (Q1.Category1 IS NULL OR Q1.Category1 IS NOT NULL AND Q1.Category1 = IL2.Category1) 
    AND 
    (Q1.Category2 IS NULL OR Q1.Category2 IS NOT NULL AND Q1.Category2 = IL2.Category2)) 
     AS DistinctCountOfItems 
FROM (SELECT 
     Category1, 
     Category2 
     FROM ItemList IL 
     GROUP BY 
     Category1, 
     Category2 
     WITH CUBE) Q1 

Aber das läuft langsam, wenn die Ergebnismenge auf Grund der Unterauswahl groß ist. Gibt es einen anderen Weg, um eine eindeutige Anzahl von einem gewürfelten Ergebnis zu erhalten?

Dies ist das Ergebnis, das ich

Category1  Category2 DistinctCountOfItems 
a    a   3 
a    b   3 
a    c   3 
a    NULL   4 
NULL   NULL   4 
NULL   a   3 
NULL   b   3 
NULL   c   3 

Antwort

6

Sie sollten wie so Antwort Ihre "chaotisch" aufzuräumen können:

select Category1, Category2, count(distinct ItemId) 
from ItemList 
group by Category1, Category2 
UNION ALL 
select Category1, null, count(distinct ItemId) 
from ItemList 
group by Category1 
UNION ALL 
select null, Category2, count(distinct ItemId) 
from ItemList 
group by Category2 
UNION ALL 
select null, null, count(distinct ItemId) 
from ItemList 

Dann ist die andere Option kam ich mit:

select IL1.Category1, IL1.Category2, count(distinct ItemId) 
from ( 
    select Category1, Category2 
    from ItemList 
    group by Category1, Category2 
    with cube 
) IL1 
join ItemList IL2 on (IL1.Category1=IL2.Category1 and IL1.Category2=IL2.Category2) 
     or (IL1.Category1 is null and IL1.Category2=IL2.Category2) 
     or (IL1.Category2 is null and IL1.Category1=IL2.Category1) 
     or (IL1.Category1 is null and IL1.Category2 is null) 
group by IL1.Category1, IL1.Category2 

Die Leistungsfähigkeit basiert variieren kann auf den Indizes, Anzahl der Spalten gruppiert usw. Für die Test-Tabelle, die ich geschrieben habe, war die Sub-Auswahl und Join (im Gegensatz zu den Unionen) etwas besser.Ich habe im Moment keinen Zugriff auf eine MSSQL 2000-Instanz (ich habe eine Instanz 2005 getestet), aber ich glaube nicht, dass hier irgendetwas ungültig ist.

UPDATE

Eine noch bessere Option, vor allem, wenn Sie mehr als 2 Spalten sind die Gruppierung auf (Wenn Sie auf 8 Spalten der obige Code Gruppierung würde 256 Join-Klauseln erfordern alle null Kombinationen zu fangen!):

select IL1.Category1, IL1.Category2, count(distinct ItemId) 
from ( 
    select Category1, Category2 
    from ItemList 
    group by Category1, Category2 
    with cube 
) IL1 
inner join ItemList IL2 on isnull(IL1.Category1,IL2.Category1)=IL2.Category1 
        and isnull(IL1.Category2,IL2.Category2)=IL2.Category2 
group by IL1.Category1, IL1.Category2 
+0

@ chezy525 .... Netter Ansatz ... Ich mag es. Es ist definitiv effizienter als die Gewerkschaften. immer noch etwas chaotischer als ich mag, aber es funktioniert. –

+0

Danke! Das war eine lustige Abwechslung für meinen Freitag! Ich denke, jede Lösung wird "unordentlicher als es sein sollte" ohne die deutliche aggregierte Unterstützung ... – chezy525

+0

Ihre letzte Option ist die gleiche, die ich schließlich mit, es ist die eleganteste, und es trifft die Tabellen am wenigsten mal um das Ergebnis zurück zu bekommen. Soweit ich aus meinen Ausführungsplänen ersehen kann, würde ein Index für Kategorie1, Kategorie2, ElementID die Abfrage so schnell machen, wie sie würde. – cairnz

-1

Das ist sehr interessant zu sehen. Ich kann Ihre erste Abfrage in SQL Server 2008 R2 ausführen, aber die Dokumentation sagt, es wird nicht funktionieren.

Hier ist eine Variation Ihrer zweiten Abfrage, die möglicherweise besser funktioniert. Es führt die eindeutige Anzahl in der Unterabfrage und den Würfel in der äußeren Abfrage

SELECT Category1, Category2, MAX(DistinctCount) as DistinctCount 
FROM (
    SELECT Category1, Category2, COUNT(DISTINCT ItemId) as DistinctCount 
    FROM ItemList 
    GROUP BY Category1, Category2 
    ) Q1 
GROUP BY Category1, Category2 
WITH CUBE 
+0

.. tatsächlich funktioniert das nicht, wenn die Daten in der Tabelle dupliziert werden. Sehen Sie sich die überarbeiteten Daten in der Frage an. Es gibt nicht zurück, was erwartet wird. –

-1

Wie wäre es damit ??

Die innere Abfrage würde ein eindeutiges Ergebnis liefern.

SELECT ORIGINAL_ITEM.Category1, DISTINCT_ITEM.Category2, DISTINCT_ITEM.cnt 
FROM 
    (SELECT DISTINCT category2, COUNT(*) as CNT 
    FROM ItemList) DISTINCT_ITEM 
JOIN ItemList ORIGINAL_ITEM on ORIGINAL_ITEM.category2 = DISTINCT_ITEM.category2 
GROUP BY ORIGINAL_ITEM.category1, DISTINCT_ITEM.category2 
+0

dies ist nicht einmal gültig ... Sie können kein Element in der Auswahlliste einer Gruppe haben, die weder in einem Aggregat noch in der group by-Klausel enthalten ist. –

+0

Einverstanden. Habe die Abfrage nicht wirklich getestet.Wenn ich also "gruppiere nach" innere Abfrage hinzugefügt habe, wäre das eine gültige Idee? – exiter2000

+0

Nein, es wäre nicht ... danke für den Versuch –

-1

Ich habe die folgende Version:

Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (Intel X86) 2. April 2010 15.53.02 Copyright (c) Microsoft Corporation Express Edition mit advanced Services auf Windows NT 5.1 (Build 2600: Service Pack 3)

Wenn ich Ihre Abfrage ausführen

SELECT 
    Category1, 
    Category2, 
    COUNT(DISTINCT(ItemId)) 
FROM ItemList IL 
GROUP BY 
    Category1, 
    Category2 
WITH CUBE 

ich diese Ergebnisse Get

a  a  3 
a  b  3 
a  c  3 
NULL a  3 
NULL b  3 
NULL c  3 
a  NULL 4 
NULL NULL 4 
+0

Code Gunny Im Wissen, dass dies auf SQL Server 2008 funktioniert. Aber meine Frage bezieht sich auf SQL Server 2000. Ihre Buchung ist irrelevant –

+0

@John - Ich denke, ich muss mehr Aufmerksamkeit schenken die Tags, hä? –

1

Hier ist eine andere Möglichkeit, die ich fand, aber es ist extrem chaotisch. Es läuft jedoch schneller als mit einem Subselect.

SELECT 
    category1, 
    category2, 
    count(distinct itemid) 
FROM (SELECT DISTINCT 
     category1, 
     category2, 
     itemid 
     FROM ItemList 
) x 
GROUP BY category1, category2 
UNION ALL 
SELECT 
    category1, 
    NULL, 
    count(distinct itemid) 
FROM (SELECT DISTINCT 
     category1, 
     category2, 
     itemid 
     FROM ItemList 
) x 
GROUP BY category1 
UNION ALL 
SELECT 
    NULL, 
    category2, 
    count(distinct itemid) 
FROM (SELECT DISTINCT 
     category1, 
     category2, 
     itemid 
     FROM ItemList 
) x 
GROUP BY category2 
UNION ALL 
SELECT 
    NULL, 
    NULL, 
    count(distinct itemid) 
FROM (SELECT DISTINCT 
     category1, 
     category2, 
     itemid 
     FROM ItemList 
) x 
Verwandte Themen