2016-05-26 8 views
3

異なるテーブルとのカウント結合の使用方法。私の質問を見てください。ここで私はCROSS APPLYを使用しています。しかし、私は実際の結果を得ていません。 インシデントテーブルにないアイテムテーブルからすべてのアイテムを取得する方法別のテーブルからの値の使用カウント

Tabel:Inc_cat

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

表:入射

+-------------+---------+------------+-----------------+ 
| 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  | 
+-------------+---------+------------+-----------------+ 

表:アイテム

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

結果:

+---------+----------------+-----------+---------------------+ 
| 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 | 
+---------+----------------+-----------+---------------------+ 

私のクエリは:

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 

答えて

5

あなたはCROSS APPLYは必要ありません。シンプルLEFT JOINが行います。

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 

すべて項目を取得するようにあなただけの、テーブルItemで起動する必要がOPで設定した期待される結果のように、返されました。

Demo here

+0

OPが「Incident」テーブルにないアイテムに対しても「0」カウントを表示する必要がある場合は、これより優れた回答です。ただし、質問内のクエリはそうではないと示唆しています。 –

+0

@Giorgos: –

+0

@Salman問題を再現できません。私が作った編集(フィドルのデモ)をチェックしてください。 –

1

私はあなたのクエリが複雑な上にある何か、欠けている場合を除き:

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:

logged_date列を追加するとし、あなたはそれを追加する必要がありますON句にあります。あなたは、SQLインジェクションを防ぐために、今sp_executesqlの代わりEXECを使用する必要があります:あなたが唯一の3つのInc_catのことを持っている場合

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の答えは良いです。ただし、未知数がInc_catの場合は、動的に行う必要があります。ここでdynamic crosstabを利用する方法である:

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

基本的に、それはGiorgos'と答えただけのダイナミックなバージョンです。

+0

あなたの答えをありがとう、私は私のクエリとテーブルをいくつかの小さな変更を行いました。それを見てください..ありがとう –

+0

@サルマン私の更新された答えを参照してください。 –

+0

私はクエリにもう1つのフィルタを追加しました。今すぐ結果を見ることができます。 –

関連する問題