我有一个包含4个字段的表(id,Year,Week,Totals)。
我需要一个查询,我想使用join,根据年份和周字段填充零值。
在我的例子中,我需要填写第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'
答案 0 :(得分:1)
这是一个有趣的!好的,我们走了。首先,我会给你一个简单的版本,它依赖于几个假设:
在任何特定年份,您的表中每周至少有一次。 IE:此查询返回从1到52的所有数字:
从您的__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