在MSSQL中向结果集添加新行

时间:2013-07-15 10:37:17

标签: sql-server pivot

我在MSSQL 2008 R2中运行SQL查询,该查询应始终返回一致的结果集,这意味着应显示所选日期范围内的所有日期,尽管数据库中的特定日期内没有行/值日期范围。例如,对于id为1和2的值,2013-07-03 - 2013-07-04的日期应如此。

情景1

Date-hour, value, id
2013-07-03-1, 10, 1
2013-07-03-2, 12, 1
2013-07-03-...
2013-07-03-24, 9, 1
2013-07-04-1, 10, 1
2013-07-04-2, 10, 1
2013-07-04-...
2013-07-04-24, 10, 1

2013-07-03-1, 11, 2 
2013-07-03-2, 12, 2
2013-07-03-...
2013-07-03-24, 9, 2
2013-07-04-1, 10, 2
2013-07-04-2, 12, 2
2013-07-04-...
2013-07-04-24, 10, 2

但是,如果id 2缺少2013-07-04的值,我通常只会得到一个如下所示的结果集: 情景2

Date-hour, value, id
2013-07-03-1, 10, 1
2013-07-03-2, 12, 1
2013-07-03-...
2013-07-03-24, 9, 1
2013-07-04-1, 10, 1
2013-07-04-2, 10, 1
2013-07-04-...
2013-07-04-24, 10, 1

2013-07-03-1, 11, 2 
2013-07-03-2, 12, 2
2013-07-03-...
2013-07-03-24, 9, 2

场景2将创建一个会影响输出的不一致结果集。是否有任何方法可以使SQL查询始终作为方案1返回,即使存在缺失值,因此如果日期范围内的特定日期没有值,则至少返回NULL。如果结果集返回id 1和2,则应覆盖id 1和2的所有日期。如果返回id 1,2和3,则应覆盖id 1,2和3的所有日期。

我有两个看起来像这样的表:

tbl_measurement
    id, date, hour1, hour2, ..., hour24

tbl_plane
    planeId, id, maxSpeed

我运行的SQL查询如下所示:

SELECT DISTINCT hour00_01, hour01_02, mr.date, mr.id, maxSpeed 
FROM tbl_measurement as mr, tbl_plane as p 
WHERE (date >= '2013-07-03' AND date <= '2013-07-04') AND p.id = mr.id 
GROUP BY mr.id, mr.date, hour00_01, hour01_02, p.maxSpeed
ORDER BY mr.id, mr.date 

我一直在四处寻找,也许PIVOT表是解决这个问题的方法吗?你能帮帮我吗?如果您可以帮我解决如何为此目的编写SQL查询,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

您可以使用递归CTE生成日期列表。如果你cross join使用飞机,每个飞机每个日期会得到一行。使用left join,您可以链接测量值(如果存在)。即使未找到任何测量结果,left join也会离开该行。

例如:

declare @startDt date = '2013-01-01'
declare @endDt date = '2013-06-30'

; with  AllDates as
        (
        select  @startDt as dt
        union all
        select  dateadd(day, 1, dt)
        from    AllDates
        where   dateadd(day, 1, dt) <= @endDt
        )
select  *
from    AllDates ad
cross join
        tbl_plane p
left join
        (
        select  row_number() over (partition by Id, cast([date] as date) order by id) rn
        ,       *
        from    tbl_measurement
        where   m.inputType = 'forecast'
        ) m
on      p.Id = m.Id
        and m.date = ad.dt
        and m.rn = 1 -- Only one per day
where   p.planeType = 3
option  (maxrecursion 0)