我有2个数据库表,一个是仅包含未来日期的日历,另一个是具有库存分配的日历,其中包含数量,日期和产品ID。
总体而言,我需要一张表格,其中显示日期列表,其中任何库存分配数量在每个日期旁边分组为单个总计。
这是仅包含7月日期的日历:
CREATE TABLE `calendar` (
`datefield` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
LOCK TABLES `calendar` WRITE;
INSERT INTO `calendar` (`datefield`) VALUES
('2012-07-01'),('2012-07-02'),('2012-07-03'),('2012-07-04'),('2012-07-05'),
('2012-07-06'),('2012-07-07'),('2012-07-08'),('2012-07-09'),('2012-07-10'),
('2012-07-11'),('2012-07-12'),('2012-07-13'),('2012-07-14'),('2012-07-15'),
('2012-07-16'),('2012-07-17'),('2012-07-18'),('2012-07-19'),('2012-07-20'),
('2012-07-21'),('2012-07-22'),('2012-07-23'),('2012-07-24'),('2012-07-25'),
('2012-07-26'),('2012-07-27'),('2012-07-28'),('2012-07-29'),('2012-07-30'),
('2012-07-31');
UNLOCK TABLES;
这是股票分配表:
CREATE TABLE `stock_allocation` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`product_ID` int(11) NOT NULL,
`date` date NOT NULL,
`quantity` int(11) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
LOCK TABLES `stock_allocation` WRITE;
INSERT INTO `stock_allocation` (`ID`, `product_ID`, `date`, `quantity`) VALUES
(1,3,'2012-07-30',50),
(2,3,'2012-07-26',40),
(3,3,'2012-07-26',100),
(4,3,'2012-07-02',200),
(5,3,'2012-07-01',134);
UNLOCK TABLES;
我运行的查询给了我最接近我需要的信息:
SELECT
calendar.datefield AS date_allocation,
IFNULL(SUM(stock_allocation.quantity),0) AS total_allocation
FROM
stock_allocation
RIGHT JOIN
calendar ON DATE(stock_allocation.date) = calendar.datefield
WHERE
calendar.datefield >= '2012-12-01' AND
calendar.datefield <='2012-12-31'
GROUP BY
date_allocation
所以这给出了类似于我所需要的东西:
+-----------------+------------------+
| date_allocation | total_allocation |
+-----------------+------------------+
| 2012-07-01 | 134 |
| 2012-07-02 | 200 |
| 2012-07-03 | 0 |
| 2012-07-04 | 0 |
| 2012-07-05 | 0 |
| 2012-07-06 | 0 |
| 2012-07-07 | 0 |
etc etc
| 2012-07-22 | 0 |
| 2012-07-23 | 0 |
| 2012-07-24 | 0 |
| 2012-07-25 | 0 |
| 2012-07-26 | 140 |
| 2012-07-27 | 0 |
| 2012-07-28 | 0 |
| 2012-07-29 | 0 |
| 2012-07-30 | 50 |
| 2012-07-31 | 0 |
+-----------------+------------------+
但是我想在这个最后的WHERE子句中添加以进行查询:
SELECT
calendar.datefield AS date_allocation,
IFNULL(SUM(stock_allocation.quantity),0) AS total_allocation
FROM
stock_allocation
RIGHT JOIN
calendar ON DATE(stock_allocation.date) = calendar.datefield
WHERE
calendar.datefield >= '2012-07-01' AND
calendar.datefield <='2012-07-31' AND
stock_allocation.product_ID = '3'
GROUP BY
date_allocation
但是这个输出会返回:
+-----------------+------------------+
| date_allocation | total_allocation |
+-----------------+------------------+
| 2012-07-26 | 140 |
| 2012-07-30 | 50 |
+-----------------+------------------+
我希望你能理解我的需要 - 考虑到包含的样本日期,我希望两个查询返回基本相同的东西,因为样本stock_allocation数据的productID始终为3.
答案 0 :(得分:1)
与其他人一样,您需要将过滤条件更改为基于product_id
字段而非ID
字段。
但是,如果您仍希望显示所有日历日期而仅对product_id = 3
行执行求和,则应将AND product_id = 3
添加到LEFT JOIN
子句而不是WHERE
条款。这样,没有连接的日历行product_id = 3
仍保留在最终结果集中而不是过滤掉(WHERE子句所做的):
SELECT
a.datefield AS date_allocation,
IFNULL(SUM(b.quantity),0) AS total_allocation
FROM
calendar a
LEFT JOIN
stock_allocation b
ON a.datefield = b.date AND
b.product_id = 3
WHERE
a.datefield BETWEEN '2012-07-01' AND '2012-07-31'
GROUP BY
a.datefield
答案 1 :(得分:0)
将AND stock_allocation.ID
更改为AND stock_allocation.product_ID
。
答案 2 :(得分:0)
不应该是stock_allocation.product_ID = '3'
而不是stock_allocation.ID = '3'
。 stock_allocation.ID将始终是唯一的,您只有1个值为'3'的条目
答案 3 :(得分:0)
您的查询没有返回行的原因是WHERE子句正在从日历中删除所有那些没有来自stock_allocation的匹配行的行。 WHERE子句正在击败OUTER JOIN,使其像INNER JOIN一样工作。
您希望在ON
子句中使用该谓词,而不是WHERE
子句。
这将为您提供所有您想要的零日历日期。
像这样:
SELECT
calendar.datefield AS date_allocation,
IFNULL(SUM(stock_allocation.quantity),0) AS total_allocation
FROM
stock_allocation
RIGHT JOIN
calendar
ON
stock_allocation.date = calendar.datefield
AND stock_allocation.product_ID = '3'
WHERE
calendar.datefield >= '2012-07-01' AND
calendar.datefield <='2012-07-31' AND
GROUP BY
date_allocation
注意:您不需要围绕stock_allocation.date
列的DATE()函数,该列的数据类型已经是DATE。