2012-08-30 49 views
2

我有一个查询,我认为应该很难做到,但是,现在我花了很多时间,仍然无法按照我想要的方式获取它,所以我希望这里有人能帮助我。SQL Server查询连接多个表

基本上,我需要创建一个报告,为每个区域提供每个月的价值。但是,并非所有地区每个月都会提供数据;在这种情况下,该视图应该在该月份和区域返回NULL。因此,认为需要看是这样的:

Month  Area Value 
2012-08-01 Area1 2 
2012-08-01 Area2 3 
2012-09-01 Area1 3 
2012-09-01 Area2 NULL 

我的数据表看起来像这样

Date  Area Value 
2012-08-01 Area1 2 
2012-08-01 Area2 3 
2012-09-01 Area1 3 -- Notice that Area2 is not present for September here 

我有一个表的所有可用区域 此外,我创建了一个表 - 该函数返回从给定日期到现在的所有日期。

例如本声明

SELECT * FROM Periods_Months('2012-01-01') 

将返回8条记录,如:

DateValue   Year Month YearMonth 
2012-01-01 00:00:00.000 2012 1 20121 
2012-02-01 00:00:00.000 2012 2 20122 
2012-03-01 00:00:00.000 2012 3 2
2012-04-01 00:00:00.000 2012 4 20124 
2012-05-01 00:00:00.000 2012 5 20125 
2012-06-01 00:00:00.000 2012 6 20126 
2012-07-01 00:00:00.000 2012 7 20127 
2012-08-01 00:00:00.000 2012 8 20128 

基础上提出的建议,我的查询现在看起来是这样的:

WITH months AS (
    SELECT DateValue, YearMonth FROM Periods_Months('2011-01-01') 
) 
select m.DateValue 
     ,CAST(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,m.DateValue)+1,0)) AS Date) AS DateReported -- Get last day in month 
     ,ResponseTime AS Value 
     ,g.ExternalId 
from GISDB.dbo.GisObjects g 
CROSS JOIN months m 
LEFT OUTER JOIN 
(-- SELECT data from data table, grouped by area and month 
SELECT dbo.YearMonth(CloseDate) AS YearMonth 
     ,MAX(CloseDate) AS LastDate 
     ,GisObjectId 
     ,SUM(DATEDIFF(HH,RegDate,CloseDate)) AS ResponseTime -- calculate response time between start and end data (the value we need) 
FROM DataTable 
WHERE CloseDate IS NOT NULL 
AND  GisObjectId IS NOT NULL 
GROUP BY GisObjectId, dbo.YearMonth(CloseDate) -- group by area and month 
) c 
ON g.ObjectId = c.GisObjectId AND c.YearMonth = m.YearMonth 
WHERE g.CompanyId = 3 AND g.ObjectTypeId = 1 -- reduce the GIS objects that we compare to 
ORDER BY m.DateValue, g.ObjectId 

但结果是(值始终为空):

DateValue     DateReported Value ExternalId 
2011-01-01 00:00:00.000 31-01-2011 NULL 9994 
2011-01-01 00:00:00.000 31-01-2011 NULL 9993 
2011-01-01 00:00:00.000 31-01-2011 NULL 9992 
2011-01-01 00:00:00.000 31-01-2011 NULL 9991 
2011-01-01 00:00:00.000 31-01-2011 NULL 2339 
2011-01-01 00:00:00.000 31-01-2011 NULL 2338 
2011-01-01 00:00:00.000 31-01-2011 NULL 2337 
2011-01-01 00:00:00.000 31-01-2011 NULL 2336 
2011-01-01 00:00:00.000 31-01-2011 NULL 2335 
2011-01-01 00:00:00.000 31-01-2011 NULL 2334 
2011-01-01 00:00:00.000 31-01-2011 NULL 2327 
2011-01-01 00:00:00.000 31-01-2011 NULL 2326 
2011-01-01 00:00:00.000 31-01-2011 NULL 2325 
2011-01-01 00:00:00.000 31-01-2011 NULL 2324 
2011-01-01 00:00:00.000 31-01-2011 NULL 2323 
2011-01-01 00:00:00.000 31-01-2011 NULL 2322 

+2

哎呀,格式化疯了。希望它仍然是可以理解的... – user1632306

+4

欢迎来到StackOverflow:如果您发布代码,XML或数据样本,请**在文本编辑器中突出显示这些行,然后单击“代码示例”按钮(“{}”)编辑器工具栏可以很好地格式化和语法突出显示它! –

+0

请参阅[编辑帮助](http://stackoverflow.com/editing-help)。 – hims056

回答

2

我想你有你所有的领域,我称之为area_table表。

WITH month_table AS (
    SELECT dateValue FROM Periods_Months('2012-01-01') 
) 
select * from area_table 
CROSS JOIN month_table 
LEFT OUTER JOIN myValueTable 
ON area_table.name = myValueTable.area 
AND myValueTable.date = left(convert(varchar(30),month_table.dateValue,120),10) 
ORDER BY myValueTable.Month, myValueTable.area 
+0

该查询列出了所有区域的数据,但仅列出了每个月有数据的区域。它还需要为给定月份没有数据的区域显示一行 – user1632306

+0

@ user1632306然后您用CROSS JOIN与period_month SELECT为每个区域的每个行创建每个月份,然后在值表上为LEFT OUTER JOIN。编辑我的帖子。 – LaGrandMere

+0

@ user1632306您可能需要格式化month_table.dateValue – LaGrandMere

1

假设Areas是你的所有可用区域表,t - 是您的数据表:

SELECT pm.dateValue,Ar.Area, t.value 
FROM Periods_Months('2012-01-01') pm, Areas ar 
    left join t on (pm.dateValue=t.Date) and (ar.Area=t.Area) 
order by pm.DateValue,ar.Area 
+0

那个给我一个“多部分标识符”pm.DateValue“无法绑定”。错误 – user1632306