我无法正确选择语法。请帮助
我有两个表:第一个包含工作数据
CREATE TABLE ProdStatus (
Id INT(6) UNSIGNED ZEROFILL,
ProdId INT,
StatusId INT,
Date DATE,
Total INT
);
此表中的数据:
INSERT INTO ProdStatus
VALUES
(000001, 1, 1, '2014-02-01', 5),
(000002, 1, 2, '2014-02-01', 3),
(000003, 1, 2, '2014-02-05', 4),
(000004, 2, 1, '2014-02-07', 2),
(000005, 2, 1, '2014-02-08', 7),
(000006, 2, 2, '2014-02-08', 9);
第二个是日历表
CREATE TABLE calendar (
id int(11),
Date date
);
日历表的数据:
INSERT INTO calendar (id, Date)
VALUES
(1, '2014-02-01'),
(2, '2014-02-02'),
(3, '2014-02-03'),
(4, '2014-02-04'),
(5, '2014-02-05'),
(6, '2014-02-06'),
(7, '2014-02-07'),
(8, '2014-02-08'),
(9, '2014-02-09'),
(10, '2014-02-10');
我需要能够从ProdStatus表中选择所有值的总和,按ProdId和Date分组(总和,因为我可以有多个状态)但是与日历表一起使用,因为我需要每天的值选定的范围。 如果我在ProdStatus表中没有一天的信息,那么应该返回前一天的结果。
以下是我所做的查询:
SELECT p.ProdId, c.Date, sum(p.Total) as Result
FROM ProdStatus p
right outer join calendar c on c.Date = p.Date
WHERE p.ProdId in (1, 2)
and c.date between '2014-02-01' and '2014-02-10'
group by c.date, p.ProdId
此查询返回此结果:
ProdId Date Result 1 2014-02-01 8 1 2014-02-05 4 2 2014-02-07 2 2 2014-02-08 16
预期结果:
ProdId Date Result 1 2014-02-01 8 2 2014-02-01 0 1 2014-02-02 8 2 2014-02-02 0 1 2014-02-03 8 2 2014-02-03 0 1 2014-02-04 8 2 2014-02-04 0 1 2014-02-05 4 2 2014-02-05 0 1 2014-02-06 4 2 2014-02-06 0 1 2014-02-07 4 2 2014-02-07 2 1 2014-02-08 4 2 2014-02-08 16 1 2014-02-09 4 2 2014-02-09 16 1 2014-02-10 4 2 2014-02-10 16
有什么建议吗? 谢谢
答案 0 :(得分:0)
这似乎是编程语言的任务。你是如何消费结果的?你能用这种语言实现这个目标吗?
如果您需要这是一个100%的mysql解决方案,您可能需要编写一个存储过程来执行此操作,而不仅仅是一个简单的查询。
答案 1 :(得分:0)
这是我的sqlfiddle。有一个派生表,表示列表产品ID,以确保每个日历日期的每个产品都有一个条目。
SELECT foo.p AS ProdId, calendar.Date, SUM(COALESCE(ProdStatus.Total,0)) as Result
FROM calendar
JOIN (SELECT 1 AS p UNION SELECT 2) AS foo
LEFT JOIN ProdStatus
ON calendar.Date >= ProdStatus.Date
AND foo.p = ProdStatus.ProdId
LEFT JOIN ProdStatus AS t1
ON calendar.Date >= t1.Date
AND ProdStatus.Date < t1.Date
AND foo.p = t1.ProdId
WHERE calendar.date BETWEEN '2014-02-01' AND '2014-02-10'
AND t1.Id IS NULL
GROUP BY calendar.date, foo.p
ORDER BY calendar.date, foo.p;
以下是使用您的Product表(假设密钥称为ID):
SELECT product.id AS ProdId, calendar.Date, SUM(COALESCE(ProdStatus.Total,0)) as Result
FROM calendar
JOIN Product
LEFT JOIN ProdStatus
ON calendar.Date >= ProdStatus.Date
AND product.id = ProdStatus.ProdId
LEFT JOIN ProdStatus AS t1
ON calendar.Date >= t1.Date
AND ProdStatus.Date < t1.Date
AND product.id = t1.ProdId
WHERE calendar.date BETWEEN '2014-02-01' AND '2014-02-10'
AND t1.Id IS NULL
AND product.id IN (1, 2, 253, 54, 78)
GROUP BY calendar.date, product.id
ORDER BY calendar.date, product.id;
答案 2 :(得分:0)
我将您的查询切换为left outer join
,只是因为我更好地按照这种方式查询查询(“在进行连接时保留第一个表中的所有行”)。
您只需将prodid
上的条件从where
子句移到on
子句:
SELECT p.ProdId, c.Date, sum(p.Total) as Result
FROM calendar c left outer join
ProdStatus p
on c.Date = p.Date and p.ProdId in (1, 2)
WHERE c.date between '2014-02-01' and '2014-02-10'
group by c.date, p.ProdId
order by c.date, p.ProdId;
如果没有匹配项,则prodiId
为NULL
,因此where
子句中的条件失败。
编辑:
我明白了。要解决此类查询,您需要生成两个prodids和日期的所有可能组合,然后加入prod状态:
SELECT prods.ProdId, c.date, coalesce(sum(p.Total), 0) as Result
FROM (select 1 as ProdId union all select 2) as prods cross join
calendar c left outer join
ProdStatus p
on c.Date = p.Date and prods.ProdId = p.ProdId
WHERE c.date between '2014-02-01' and '2014-02-10'
GROUP BY prods.ProdId, c.date
OPRDER BY prods.ProdId, c.date;