如何编写SQL查询以“扩展”当前具有表示重复记录的字段的表?

时间:2016-04-05 23:58:51

标签: sql sql-server

我需要一个包含每个月记录的表,而不是包含重复计数字段的表。

我的数据目前看起来像这样:

Property       Item        Month          Repeat_Count      Amount
------------------------------------------------------------------
A              Rent        1/1/2016        1                100
A              Rent        2/1/2016        1                105
A              Rent        3/1/2016        3                110
A              Rent        6/1/2016        1                115
A              Rent        7/1/2016        6                120
A              Rent        1/1/2017        1                125

我希望它看起来像这样:

Property   Item      Month         Amount
-----------------------------------------
A          Rent      1/1/2016      100
A          Rent      2/1/2016      105
A          Rent      3/1/2016      110
A          Rent      4/1/2016      110
A          Rent      5/1/2016      110
A          Rent      6/1/2016      115
A          Rent      7/1/2016      120
A          Rent      8/1/2016      120
A          Rent      9/1/2016      120
A          Rent      10/1/2016     120
A          Rent      11/1/2016     120
A          Rent      12/1/2016     120
A          Rent      1/1/2017      125

希望我能很好地解释这个,谢谢!

2 个答案:

答案 0 :(得分:2)

我使用table of numbersCROSS APPLY

数字表只是一个表,其中一列的整数从1到足够大,例如100,000。我个人使用100K数字的表。 Aaron Bertrand写了一篇good article来解释如何生成这样的表格。

示例数据

DECLARE @T TABLE ([Property] varchar(50), [Item] varchar(50), [Month] datetime, [Repeat_Count] int, [Amount] int);

INSERT INTO @T ([Property], [Item], [Month], [Repeat_Count], [Amount]) VALUES
('A', 'Rent', '2016-01-01 00:00:00', 1, 100),
('A', 'Rent', '2016-02-01 00:00:00', 1, 105),
('A', 'Rent', '2016-03-01 00:00:00', 3, 110),
('A', 'Rent', '2016-06-01 00:00:00', 1, 115),
('A', 'Rent', '2016-07-01 00:00:00', 6, 120),
('A', 'Rent', '2017-01-01 00:00:00', 1, 125);

<强>查询

SELECT *
FROM
    @T AS T
    CROSS APPLY
    (
        SELECT
            DATEADD(day, dbo.Numbers.Number-1, T.Month) AS NewDate
        FROM dbo.Numbers
        WHERE dbo.Numbers.Number <= T.Repeat_Count
    ) AS CA
ORDER BY NewDate;

<强>结果

+----------+------+-------------------------+--------------+--------+-------------------------+
| Property | Item |          Month          | Repeat_Count | Amount |         NewDate         |
+----------+------+-------------------------+--------------+--------+-------------------------+
| A        | Rent | 2016-01-01 00:00:00.000 |            1 |    100 | 2016-01-01 00:00:00.000 |
| A        | Rent | 2016-02-01 00:00:00.000 |            1 |    105 | 2016-02-01 00:00:00.000 |
| A        | Rent | 2016-03-01 00:00:00.000 |            3 |    110 | 2016-03-01 00:00:00.000 |
| A        | Rent | 2016-03-01 00:00:00.000 |            3 |    110 | 2016-03-02 00:00:00.000 |
| A        | Rent | 2016-03-01 00:00:00.000 |            3 |    110 | 2016-03-03 00:00:00.000 |
| A        | Rent | 2016-06-01 00:00:00.000 |            1 |    115 | 2016-06-01 00:00:00.000 |
| A        | Rent | 2016-07-01 00:00:00.000 |            6 |    120 | 2016-07-01 00:00:00.000 |
| A        | Rent | 2016-07-01 00:00:00.000 |            6 |    120 | 2016-07-02 00:00:00.000 |
| A        | Rent | 2016-07-01 00:00:00.000 |            6 |    120 | 2016-07-03 00:00:00.000 |
| A        | Rent | 2016-07-01 00:00:00.000 |            6 |    120 | 2016-07-04 00:00:00.000 |
| A        | Rent | 2016-07-01 00:00:00.000 |            6 |    120 | 2016-07-05 00:00:00.000 |
| A        | Rent | 2016-07-01 00:00:00.000 |            6 |    120 | 2016-07-06 00:00:00.000 |
| A        | Rent | 2017-01-01 00:00:00.000 |            1 |    125 | 2017-01-01 00:00:00.000 |
+----------+------+-------------------------+--------------+--------+-------------------------+

答案 1 :(得分:1)

您可以使用Tally Table生成日期:

WITH E1(N) AS( -- 10 ^ 1 = 10 rows
    SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b), -- 10 ^ 2 = 100 rows
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b), -- 10 ^ 4 = 10,000 rows
CteTally(N) AS(
    SELECT TOP(SELECT MAX(Repeat_Count) FROM tbl) ROW_NUMBER() OVER(ORDER BY(SELECT NULL))
    FROM E4
)
SELECT
    t.Property,
    t.Item,
    [Month] = DATEADD(MONTH, c.N-1, t.Month),
    t.Amount
FROM tbl t
INNER JOIN CteTally c
    ON c.N <= t.Repeat_Count
ORDER BY t.Property, t.Item, [Month]