我有一个类似于下面的查询,显示了几个表的记录计数。
SELECT 'SomeTable' as tname, COUNT(*) as ttlRecords FROM SomeTable WHERE SubjectID = @SubjectID
UNION
SELECT 'AnotherTable' as tname, COUNT(*) as ttlRecords FROM AnotherTable WHERE SubjectID = @SubjectID
UNION
SELECT 'YetAnotherTable' as tname, COUNT(*) as ttlRecords FROM YetAnotherTable WHERE SubjectVersionID = @SubjectVersionID
结果看起来像这样......
tname ttlRecords
SomeTable 25
AnotherTable 55
YetAnotherTable 120
现在,我想修改它以进一步显示具有特定条件的一些计数。对于此示例,我有一个RegionID,指定记录是与加拿大或美国地区相关联。所以我想在ttlRecordCount的同一行显示USRecordCount和CARecordCount,如下所示......
tname ttlRecords USRecordCount CARecordCount
SomeTable 25 10 15
AnotherTable 55 52 3
YetAnotherTable 120 100 20
我知道我可以使用子查询来执行此操作,如下所示,但它似乎很草率且可能很慢。
SELECT
'SomeTable' as tname,
(SELECT COUNT(*) FROM SomeTable WHERE SubjectID = @SubjectID) as ttlRecords,
(SELECT COUNT(*) FROM SomeTable WHERE SubjectID = @SubjectID AND RegionTypeID = 1) as USRecordCount,
(SELECT COUNT(*) FROM SomeTable WHERE SubjectID = @SubjectID AND RegionTypeID = 2) as CARecordCount
UNION
SELECT
'AnotherTable' as tname,
(SELECT COUNT(*) FROM AnotherTable WHERE SubjectID = @SubjectID) as ttlRecords,
(SELECT COUNT(*) FROM AnotherTable WHERE SubjectID = @SubjectID AND RegionTypeID = 1) as USRecordCount,
(SELECT COUNT(*) FROM AnotherTable WHERE SubjectID = @SubjectID AND RegionTypeID = 2) as CARecordCount
UNION
SELECT
'YetAnotherTable' as tname,
(SELECT COUNT(*) FROM YetAnotherTable WHERE SubjectVersionID = @SubjectVersionID) as ttlRecords,
(SELECT COUNT(*) FROM YetAnotherTable WHERE SubjectVersionID = @SubjectVersionID AND RegionTypeID = 1) as USRecordCount,
(SELECT COUNT(*) FROM YetAnotherTable WHERE SubjectVersionID = @SubjectVersionID AND RegionTypeID = 2)as CARecordCount
我的问题是,有更好的方式来写这个吗?
答案 0 :(得分:2)
您可以在SUM()语句
中使用case语句SUM(CASE WHEN A = B THEN 1 ELSE 0 END) as WhenAEqualsB
更新了原始信息:
SELECT
'SomeTable' as tname,
COUNT(1) as ttlRecords,
SUM(CASE WHEN RegionTypeID = 1 THEN 1 ELSE 0 END) as USRecordCount,
SUM(CASE WHEN RegionTypeID = 2 THEN 1 ELSE 0 END) as CARecordCount
From
SomeTable
where
SubjectID = @SubjectID
UNION
SELECT
'AnotherTable' as tname,
COUNT(1) as ttlRecords,
SUM(CASE WHEN RegionTypeID = 1 THEN 1 ELSE 0 END) as USRecordCount,
SUM(CASE WHEN RegionTypeID = 2 THEN 1 ELSE 0 END) as CARecordCount
FROM
AnotherTable
where
SubjectID = @SubjectID
UNION
SELECT
'YetAnotherTable' as tname,
COUNT(1) as ttlRecords,
SUM(CASE WHEN RegionTypeID = 1 THEN 1 ELSE 0 END) as USRecordCount,
SUM(CASE WHEN RegionTypeID = 2 THEN 1 ELSE 0 END) as CARecordCount
FROM
YetAnotherTable
where
SubjectID = @SubjectID
答案 1 :(得分:2)
是的,可以使用模式
SELECT
SUM(CASE WHEN <condition_1> THEN 1 ELSE 0 END) AS NumCond1,
SUM(CASE WHEN <condition_2> THEN 1 ELSE 0 END) AS NumCond2,
....
SUM(CASE WHEN <condition_N> THEN 1 ELSE 0 END) AS NumCondN
FROM <table_name>
这将需要对表中的所有记录进行一次迭代。每个记录将由每个聚合表达式(SUM
s)进行评估,并且只有在记录与相应条件匹配时才会增加计数。
请注意,这可能不会更快;它可能会慢得多!考虑这样一种情况,即表包含10亿条记录,但每条条件只有1条记录匹配,并且条件中使用的每个列组合都有索引。在这种情况下,使用索引直接找到那些少量记录比读取所有10亿行以找到它们要快得多。也就是说,使用问题中描述的seaprate子查询方法。这仅适用于您不需要计算总行数的情况,如下例所示。
以下是使用其他优化进行转换的完整示例,该示例可能适用于您的实际工作,将任何常见条件移至WHERE
子句中。请注意使用COUNT(*)
同时获取总行数。
SELECT
'SomeTable' as tname,
COUNT(*) as ttlRecords,
SUM(CASE WHEN RegionTypeID = 1 THEN 1 ELSE 0 END) as USRecordCount,
SUM(CASE WHEN RegionTypeID = 2 THEN 1 ELSE 0 END) as CARecordCount
FROM SomeTable
WHERE SubjectID = @SubjectID
UNION ALL
SELECT
'AnotherTable' as tname,
COUNT(*) as ttlRecords,
SUM(CASE WHEN RegionTypeID = 1 THEN 1 ELSE 0 END) as USRecordCount,
SUM(CASE WHEN RegionTypeID = 2 THEN 1 ELSE 0 END) as CARecordCount
FROM AnotherTable
WHERE SubjectID = @SubjectID
UNION ALL
SELECT
'YetAnotherTable' as tname,
COUNT(*) as ttlRecords,
SUM(CASE WHEN RegionTypeID = 1 THEN 1 ELSE 0 END) as USRecordCount,
SUM(CASE WHEN RegionTypeID = 2 THEN 1 ELSE 0 END) as CARecordCount
FROM YetAnotherTable
WHERE SubjectVersionID = @SubjectVersionID