2016-05-26 8 views
3

Verwenden Sie count Join mit verschiedenen Tabellen. Bitte werfen Sie einen Blick auf meine Fragen. Hier verwende ich CROSS APPLY. Aber ich bekomme nicht das tatsächliche Ergebnis. Wie kann ich alle Artikel aus der Artikeltabelle nicht in der Ereignistabelle erhalten.Wie verwenden Sie count für Wert aus einer anderen Tabelle

Tabel: Inc_cat

+------------+--------------+--+ 
| inc_cat_id | inc_cat_n | | 
+------------+--------------+--+ 
|   1 | Support  | | 
|   2 | PM   | | 
|   3 | Installation | | 
+------------+--------------+--+ 

Tabelle: Vorfall

+-------------+---------+------------+-----------------+ 
| incident_id | item_id | inc_cat_id | date_logged  | 
+-------------+---------+------------+-----------------+ 
|   100 |  555 |   1 | 2016-01-01  | 
|   101 |  555 |   2 | 2016-01-18  | 
|   103 |  444 |   3 | 2016-02-10  | 
|   104 |  444 |   2 | 2016-04-01  | 
|   105 |  666 |   1 | 2016-04-09  | 
|   106 |  555 |   2 | 2016-04-20  | 
+-------------+---------+------------+-----------------+ 

Tabelle: Artikel

+---------+---------+--+ 
| item_id | cust_id | | 
+---------+---------+--+ 
|  444 |  34 | | 
|  555 |  34 | | 
|  666 |  76 | | 
|  333 |  34 | | 
|  222 |  34 | | 
|  111 |  34 | | 
+---------+---------+--+ 

Ergebnis:

+---------+----------------+-----------+---------------------+ 
| item_id | count(Support) | count(PM) | count(Installation) | 
+---------+----------------+-----------+---------------------+ 
|  555 |    0 |   1 |     0 | 
|  444 |    0 |   1 |     0 | 
|  666 |    0 |   0 |     0 | 
|  333 |    0 |   0 |     0 | 
|  222 |    0 |   0 |     0 | 
|  111 |    0 |   0 |     0 | 
+---------+----------------+-----------+---------------------+ 

Meine Suche:

SELECT i.item_ID, 
COUNT(CASE WHEN i.inc_cat_id = ic.inc_cat_id AND i.inc_cat_id = 1 THEN 1 END) AS cntSupport, 
COUNT(CASE WHEN i.inc_cat_id = ic.inc_cat_id AND i.inc_cat_id = 2 THEN 1 END) AS cntPM, 
COUNT(CASE WHEN i.inc_cat_id = ic.inc_cat_id AND i.inc_cat_id = 3 THEN 1 END) AS cntInstallation 
FROM @incident i 
CROSS APPLY @incCat ic 
WHERE (i.date_logged BETWEEN '2016-04-01' AND '2016-04-30')AND i.cust_id='34' 
GROUP BY i.item_ID 

Antwort

5

Sie brauchen keine CROSS APPLY. Ein einfaches LEFT JOIN tun:

SELECT i.item_id, 
     COUNT(CASE WHEN inc.inc_cat_id = 1 THEN 1 END) AS cntSupport, 
     COUNT(CASE WHEN inc.inc_cat_id = 2 THEN 1 END) AS cntPM, 
     COUNT(CASE WHEN inc.inc_cat_id = 3 THEN 1 END) AS cntInstallation 
FROM Item AS i 
LEFT JOIN Incident AS inc ON i.item_id = inc.item_id AND 
         inc.date_logged BETWEEN '2016-04-01' AND '2016-04-30'   
WHERE i.cust_id = 34 
GROUP BY i.item_id 

Sie müssen nur durch Tabelle Item, beginnen, um alle Artikel zurück zu bekommen, wie es in dem erwarteten Ergebnis im OP gesetzt.

Demo here

+0

Das ist eine bessere Antwort als meine, wenn das OP auch "0" -Zählung für Elemente anzeigen muss, die nicht in der "Incident" -Tabelle sind. Die Abfrage in der Frage schlägt jedoch anders vor ... –

+0

@Giorgos: Alle zählen 0 –

+0

@Salman Ich kann das Problem nicht reproduzieren. Bitte überprüfe die Bearbeitung, die ich gemacht habe (Geige-Demo). –

1

Wenn ich etwas fehlt bin, ist Ihre Anfrage über kompliziert:

SELECT item_ID, 
     COUNT(CASE WHEN .inc_cat_id = 1 THEN 1 END) AS cntSupport, 
     COUNT(CASE WHEN inc_cat_id = 2 THEN 1 END) AS cntPM, 
     COUNT(CASE WHEN inc_cat_id = 3 THEN 1 END) AS cntInstallation 
    FROM @incident 
GROUP BY item_ID 
1

UPDATE:

Mit dem Zusatz von logged_date Spalte, können Sie es nur hinzufügen müssen in der ON Klausel. Sie müssen sp_executesql statt EXEC jetzt verwenden SQL-Injection zu verhindern:

DECLARE @fromDate DATE = '2016-04-01', 
     @toDate DATE = '2016-04-30'; 

DECLARE @sql NVARCHAR(MAX) = N''; 

SELECT @sql = 
'SELECT 
    i.item_id' + CHAR(10) + 
(SELECT 
' , COUNT(CASE WHEN inc.inc_cat_id = ' + CONVERT(VARCHAR(10), inc_cat_id) + 
' THEN 1 END) AS ' + QUOTENAME('count(' + inc_cat_n + ')') + CHAR(10) 
FROM #Inc_cat 
ORDER BY inc_cat_id 
FOR XML PATH('') 
) + 
'FROM #item AS i 
LEFT JOIN #incident AS inc 
    ON i.item_id = inc.item_id 
    AND inc.date_logged BETWEEN @fromDate AND @toDate 
GROUP BY i.item_id;'; 

PRINT (@sql); 
EXEC sp_executesql 
     @sql, 
     N'@fromDate DATE, @toDate DATE', 
     @fromDate, 
     @toDate 

ONLINE DEMO


Giorgos Antwort ist gut, wenn man nur das 3 Inc_cat s haben. Wenn Sie jedoch eine unbekannte Anzahl von Inc_cat s haben, müssen Sie dies dynamisch tun. Hier ist ein Verfahren zur Herstellung eines dynamic crosstab mit:

DECLARE @sql NVARCHAR(MAX) = N''; 

SELECT @sql = 
'SELECT 
    i.item_id' + CHAR(10) + 
(SELECT 
' , COUNT(CASE WHEN inc.inc_cat_id = ' + CONVERT(VARCHAR(10), inc_cat_id) + 
' THEN 1 END) AS ' + QUOTENAME('count(' + inc_cat_n + ')') + CHAR(10) 
FROM Inc_cat 
ORDER BY inc_cat_id 
FOR XML PATH('') 
) + 
'FROM Item AS i 
LEFT JOIN Incident AS inc 
    ON i.item_id = inc.item_id 
GROUP BY i.item_id;'; 

PRINT (@sql); 
EXEC (@sql); 

ONLINE DEMO

Im Grunde ist es nur eine dynamische Version von Giorgos' Antwort.

+0

Danke für deine Antwort, ich habe ein paar kleine Änderungen an meiner Anfrage und Tabelle vorgenommen. Bitte schauen Sie in das .. Danke –

+0

@Salman sehe meine aktualisierte Antwort. –

+0

Ich habe einen weiteren Filter in meiner Abfrage hinzugefügt, lassen Sie uns jetzt das Ergebnis sehen –

Verwandte Themen