2013-04-26 89 views
1

这应该很简单,但我只是无法找到答案(我将其归咎于我已经编写SQL近14个小时的事实)。SQL左连接,交叉连接 - 查找缺失值

我有一个名为“标签”字段和“ReportYear”字段的报表。我知道我有三个可能的“标签”值,但并非每个标签都会有每年的条目。

我可以选择一个不同的标签列表和获取:

'Regular' 
'Special' 
'None' 

做一些手工数据选择在这里,我知道,在2011年和2010年有0项,并带有“特殊”,但我需要一个查询将这些信息汇总在一起,以便将其显示出来:

'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
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查询。

你也可以通过参数化整个查询来接受BeginYearEndYear或类似的东西来消除ReportYear子查询。或者,您可以从表中获得Min(ReportYear), Max(ReportYear),并且假设您在该列上有一个索引,则可以将其转换为查找(可能需要两个单独的查询来获得此查询),然后使用数字表或on-the -fly数字表格来生成它们之间的年数序列。

一旦你做了这两个更改,查询将显着改善。

+0

是的!那样做了。非常感谢! – JMax2012 2013-04-27 00:14:40

+0

不客气。 – ErikE 2013-04-27 00:18:17