SQL左连接,交叉连接 - 找到缺失的值

时间:2013-04-26 23:59:14

标签: tsql

这应该很简单,但我无法找到答案(我会因为我已经编写了近14个小时的SQL编码而将其归咎于此。)

我有一个名为report的表,其中包含“Label”字段和“ReportYear”字段。我知道我有三个可能的“标签”值,但不是每个标签都会有每年的条目。

我可以选择一个不同的标签列表,我得到:

'Regular'
'Special'
'None'

在这里做一些手动数据选择,我知道2011年和2010年有0个标签为'Special'的条目,但我需要一个查询来将这些信息整合在一起,以便它出来:

'Regular' - '2012' - '5'
'Regular' - '2011' - '2'
'Regular' - '2010' - '1'
'Special' - '2012' - '3'
'Special' - '2011' - '0'
'Special' - '2010' - '0'
'None' - '2012' - '10'
'None' - '2011' - '5'
'None' - '2010' - '2'

希望这是有道理的。

我知道我可以SELECT Count(*), Label FROM (SELECT DISTINCT Label FROM Report) t1 ......但是呢? LEFT JOIN Report t2 ON t1.Label=t2.LabelCROSS JOIN

我的大脑被炸了。

帮助?

1 个答案:

答案 0 :(得分:1)

SELECT
   L.Label,
   Y.ReportYear,
   ReportCount = Count(R.Label)
FROM
   (SELECT DISTINCT Label FROM dbo.Report) L
   CROSS JOIN (SELECT DISTINCT ReportYear FROM dbo.Report) Y
   LEFT JOIN dbo.Report R
      ON L.Label = R.Label
      AND Y.ReportYear = R.ReportYear
GROUP BY
   L.Label,
   Y.ReportYear

现在,这并不是很理想,因为你要进行两次全表扫描,只是为了得到标签和年份。

除非我误解了事情,否则在我看来,您应该对Report表进行规范化,使其具有ReportLabelID列,然后使用带有不同标签的ReportLabel表。然后,您可以将ReportLabel表放在上面DISTINCT查询的位置。

您还可以通过参数化整个查询来消除ReportYear子查询,以接受BeginYearEndYear或类似的东西。或者,您可以从表中获取Min(ReportYear), Max(ReportYear),并假设您在列上有索引,它可以将其转换为搜索(可​​能需要两个单独的查询来获取此值),然后使用数字表或即时数字表,以生成它们之间的年份序列。

完成这两项更改后,查询的效果会更好。