1

我有一个包含 4 个字段(id、Year、Week、Totals)的表。

我需要一个查询,我猜想使用连接来根据年和周字段填充零值。

在我的示例中,我需要为 2013 年第 3 周和第 4 周填充零值

Rec Id, Year, Week, Totals
1, '2012', '52', '23'
2, '2013', '1' , '9'
3, '2013', '2' , '4'

Missing record from DB -> null, '2013', '3' , '0'
Missing record from DB -> null, '2013', '4' , '0'

4, '2013', '5' , '5'
5, '2013', '6' , '6'
6, '2013', '7' , '5'
4

1 回答 1

1

那是一个有趣的!好的,我们开始吧。首先,我会给你一个简单的版本,它依赖于几个假设:

  1. 您的表中已经至少有一个条目每年
  2. 对于任何给定的年份,您的表中至少每周都有一个。IE:此查询返回从 1 到 52 的所有数字:

    从 your_table 中选择 DISTINCT 周

鉴于这些限制,这个查询应该做你想做的事:

INSERT INTO your_table (id, year, week, totals)
    SELECT null, y, w, 0 FROM (
        SELECT DISTINCT week w FROM your_table
    ) weeks
    CROSS JOIN 
    (
        SELECT DISTINCT year y FROM your_table
    ) years
    WHERE
        (y > (select min(year) from your_table) OR w > (select min(week) from your_table where `year`=y))
        AND
        (y < (select max(year) from your_table) OR w < (select max(week) from your_table where `year`=y))
        AND 
        NOT EXISTS (select year, week from your_table where `year`=y AND `week`=w)

如果条件 2 可能不满足 - 如果每年缺少几周,您可以替换此行

SELECT DISTINCT week w FROM your_table

SELECT
    (TWO_1.SeqValue + TWO_2.SeqValue + TWO_4.SeqValue + TWO_8.SeqValue + TWO_16.SeqValue + TWO_32.SeqValue) w
FROM
    (SELECT 0 SeqValue UNION ALL SELECT 1 SeqValue) TWO_1
    CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 2 SeqValue) TWO_2
    CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 4 SeqValue) TWO_4
    CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 8 SeqValue) TWO_8
    CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 16 SeqValue) TWO_16
    CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 32 SeqValue) TWO_32
HAVING w >= 1 AND w <= 52

给出这个更一般的情况:

INSERT INTO your_table (id, year, week, totals)
    SELECT null, y, w, 0 FROM (
        SELECT
            (TWO_1.SeqValue + TWO_2.SeqValue + TWO_4.SeqValue + TWO_8.SeqValue + TWO_16.SeqValue + TWO_32.SeqValue) w
        FROM
            (SELECT 0 SeqValue UNION ALL SELECT 1 SeqValue) TWO_1
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 2 SeqValue) TWO_2
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 4 SeqValue) TWO_4
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 8 SeqValue) TWO_8
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 16 SeqValue) TWO_16
            CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 32 SeqValue) TWO_32
        HAVING w >= 1 AND w <= 52
    ) weeks
    CROSS JOIN 
    (
        SELECT DISTINCT year y FROM your_table
    ) years
    WHERE
        (y > (select min(year) from your_table) OR w > (select min(week) from your_table where `year`=y))
        AND
        (y < (select max(year) from your_table) OR w < (select max(week) from your_table where `year`=y))
        AND 
        NOT EXISTS (select year, week from your_table where `year`=y AND `week`=w)

(如果不满足条件 1,您可以使用类似的技术来生成年份列表,但我猜您没有整整一年的漏洞。)

最后,如果您有一个年和周的唯一索引,则可以稍微简化一下。如果您还没有这样的索引,您可以像这样创建它:

ALTER TABLE `your_table` ADD CONSTRAINT date UNIQUE (
`year`,
`week`
)

如果你愿意,你可以在完成后将其删除,如下所示:

ALTER TABLE `your_table` DROP INDEX date;

在这种情况下,可以删除 where 子句的最后部分:

AND 
NOT EXISTS (select year, week from your_table where `year`=y AND `week`=w)

因为 INSERT IGNORE 将跳过已经存在该唯一年/周组合的任何行。

感谢这个范围生成代码的答案:https ://stackoverflow.com/a/8349837/160565

于 2013-02-20T00:48:49.510 回答