如何使用count连接不同的表。请看看我的疑问。我在这里使用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
答案 0 :(得分: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中预期的结果集一样。
答案 1 :(得分: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
答案 2 :(得分:1)
<强>更新强>
添加logged_date
列后,您只需将其添加到ON
子句中即可。您现在需要使用sp_executesql
而不是EXEC
来阻止sql注入:
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
如果你只有3 Inc_cat
,那么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);
基本上,它只是Giorgos答案的动态版本。