填写稀疏数据中的日期差距

时间:2014-10-22 02:02:21

标签: sql sql-server database tsql common-table-expression

如果这是一个新手问题我很抱歉,但我很难找到解决方案,因为我对SQL的了解并不是很好。下面是我的数据集的一个简单示例。该表可以有1种样式或15,000种样式,解决方案需要填充空白,单位= 0表示月份间隙

Style    Month  Units
108 P 000   1   82
108 P 000   2   83
108 P 000   3   84
108 P 000   4   36
108 P 000   5   127
108 P 000   6   34
108 P 000   7   83
108 P 000   8   128
108 P 000   9   162
108 P 000   10  78
108 P 000   11  55
108 P 000   12  99
109 B5 000  2   120
109 B5 000  4   360
109 B5 000  6   648
109 B5 000  7   360
109 B5 000  8   600

下面是我正在努力争取的所需输出的简单示例。

Style     Month Units
108 P 000   1   82
108 P 000   2   83
108 P 000   3   84
108 P 000   4   36
108 P 000   5   127
108 P 000   6   34
108 P 000   7   83
108 P 000   8   128
108 P 000   9   162
108 P 000   10  78
108 P 000   11  55
108 P 000   12  99
109 B5 000  1   0
109 B5 000  2   120
109 B5 000  3   0
109 B5 000  4   360
109 B5 000  5   0
109 B5 000  6   648
109 B5 000  7   360
109 B5 000  8   600
109 B5 000  9   0
109 B5 000  10  0
109 B5 000  11  0
109 B5 000  12  0

我在这个网站上找到了一个使用递归CTE的示例解决方案,我已经适应了我的数据集:

;WITH CTE_MinMax AS
(
    SELECT Style, MIN(Month) AS MinMonth, MAX(Month) AS MaxMonth
FROM dbo.orders
GROUP BY Style
)
,CTE_Months AS
(
SELECT Style, MinMonth AS Month
FROM CTE_MinMax
UNION ALL
SELECT c.Style, Month + 1 FROM CTE_Months c
INNER JOIN CTE_MinMax mm ON c.Style = mm.Style
WHERE Month + 1 <= MaxMonth
)
SELECT c.* , COALESCE(o.Units, 0)
FROM CTE_Months c
LEFT JOIN Orders o ON c.Style = o.Style AND c.Month = o.Month
ORDER BY Style, Month
OPTION (MAXRECURSION 0)

然而,如下面的输出中所述,样式109 B5 000仅使用2到8的月份范围

Style     Month Units
108 P 000   1   82
108 P 000   2   83
108 P 000   3   84
108 P 000   4   36
108 P 000   5   127
108 P 000   6   34
108 P 000   7   83
108 P 000   8   128
108 P 000   9   162
108 P 000   10  78
108 P 000   11  55
108 P 000   12  99
109 B5 000  2   120
109 B5 000  3   0
109 B5 000  4   360
109 B5 000  5   0
109 B5 000  6   648
109 B5 000  7   360
109 B5 000  8   600

非常感谢能够帮助我实现所需输出的任何帮助。

3 个答案:

答案 0 :(得分:1)

你走了。我将您的示例数据设置为表变量,但您可以用您的表名替换我的@Data引用。

--Style    Month  Units
DECLARE @Data TABLE ([Style] VARCHAR(15), [Month] INT, Units INT)
INSERT @Data
    SELECT '108 P 000','1','82' UNION ALL
    SELECT '108 P 000','2','83' UNION ALL
    SELECT '108 P 000','3','84' UNION ALL
    SELECT '108 P 000','4','36' UNION ALL
    SELECT '108 P 000','5','127' UNION ALL
    SELECT '108 P 000','6','34' UNION ALL
    SELECT '108 P 000','7','83' UNION ALL
    SELECT '108 P 000','8','128' UNION ALL
    SELECT '108 P 000','9','162' UNION ALL
    SELECT '108 P 000','10','78' UNION ALL
    SELECT '108 P 000','11','55' UNION ALL
    SELECT '108 P 000','12','99' UNION ALL
    SELECT '109 B5 000','2','120' UNION ALL
    SELECT '109 B5 000','4','360' UNION ALL
    SELECT '109 B5 000','6','648' UNION ALL
    SELECT '109 B5 000','7','360' UNION ALL
    SELECT '109 B5 000','8','600'
;WITH Months AS (
    SELECT 1 AS [Month]
    UNION ALL
    SELECT [Month] + 1
    FROM Months
    WHERE [Month] < 12
), Styles AS (
    SELECT DISTINCT Style FROM @Data
)
SELECT
    Styles.Style,
    Months.[Month],
    SUM(COALESCE(Data.Units, 0)) AS [Units]
FROM Months
    CROSS JOIN Styles
    LEFT OUTER JOIN @Data Data
        ON Data.Style = Styles.Style
            AND Data.[Month] = Months.[Month]
GROUP BY
    Styles.Style,
    Months.[Month]
ORDER BY Style, [Month]

结果

Style           Month       Units
--------------- ----------- -----------
108 P 000       1           82
108 P 000       2           83
108 P 000       3           84
108 P 000       4           36
108 P 000       5           127
108 P 000       6           34
108 P 000       7           83
108 P 000       8           128
108 P 000       9           162
108 P 000       10          78
108 P 000       11          55
108 P 000       12          99
109 B5 000      1           0
109 B5 000      2           120
109 B5 000      3           0
109 B5 000      4           360
109 B5 000      5           0
109 B5 000      6           648
109 B5 000      7           360
109 B5 000      8           600
109 B5 000      9           0
109 B5 000      10          0
109 B5 000      11          0
109 B5 000      12          0

答案 1 :(得分:1)

不使用递归CTE的另一种方法:

create table #temp(
    style varchar(100),
    month int,
    value int
)
insert into #temp
select '108 P 000', 1, 82 union all
select '108 P 000', 2, 83 union all
select '108 P 000', 3, 84 union all
select '108 P 000', 4, 36 union all
select '108 P 000', 5, 127 union all
select '108 P 000', 6, 34 union all
select '108 P 000', 7, 83 union all
select '108 P 000', 8, 128 union all
select '108 P 000', 9, 162 union all
select '108 P 000', 10, 78 union all
select '108 P 000', 11, 55 union all
select '108 P 000', 12, 99 union all
select '109 B5 000', 2, 120 union all
select '109 B5 000', 4, 360 union all
select '109 B5 000', 6, 648 union all
select '109 B5 000', 7, 360 union all
select '109 B5 000', 8, 600

--select * from #temp

;with months(m) as(
    select 1 union all select 2 union all select 3 union all
    select 4 union all select 5 union all select 6 union all
    select 7 union all select 8 union all select 9 union all
    select 10 union all select 11 union all select 12
)
select
    s.style,
    m.m,
    value = isnull(t.value, 0)
from months m
cross join(
    select distinct style from #temp
) s
left join #temp t
    on t.month = m.m
    and t.style = s.style
order by s.style, m.m

drop table #temp

答案 2 :(得分:0)

看看这种方法是否有助于你......

Declare @Month Table
([Month] Int)
Insert into @Month 
values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)

Declare @Style Table
(Style varchar(40),Month int, Units int)
Insert into @Style
values
('109 B5 000',2,120),
('109 B5 000',4,360),
('109 B5 000',6,648)

Select      LU.Style,
            M.Month,
            Isnull(S.Units,0)
From        @Month M 
Cross join  (Select Distinct Style From @Style) LU
Left join   @Style S On  Lu.Style = S.Style And M.[Month] = S.Month

让@style成为您的源数据。在我的例子中,它只有3条记录,只有一种风格。 我的结果如下:

结果:

enter image description here