0

我有一个类似于下面的查询,它显示了几个表的记录计数。

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,它指定记录是与加拿大还是美国区域相关联。因此,我想将 USRecordCount 和 CARecordCount 与 ttlRecordCount 显示在同一行,如下所示...

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

我的问题是,有没有更好的方法来写这个?

4

2 回答 2

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
于 2013-07-26T17:05:29.663 回答
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>

这将需要仅对表中的所有记录进行一次迭代。每个记录将由每个聚合表达式(SUMs)评估,并且仅当记录与相应条件匹配时才会增加计数。

请注意,这可能不会更快;它可能会慢很多!考虑表包含 10 亿条记录但只有 1 条记录与每个条件匹配并且在条件中使用的每个列组合上都有索引的情况。在这种情况下,使用索引直接查找那几条记录要比读取所有 10 亿行来查找它们要快得多。也就是说,使用问题中描述的单独子查询方法。这仅适用于您不需要计算总行数的情况,如下例所示。

这是您通过额外优化转换的完整示例,这可能适用于您的实际工作,将任何常见条件移动到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
于 2013-07-26T17:06:12.497 回答