0

我有 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。

4

4 回答 4

1

正如其他人所说,您将希望将过滤条件更改为基于product_id字段而不是ID字段。

但是,如果您仍然希望在仅对 where 行执行求和时显示所有日历日期,则product_id = 3可以将 添加AND product_id = 3LEFT 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
于 2012-07-15T03:17:24.763 回答
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

注意:您不需要在列周围使用 DATE() 函数,该stock_allocation.date列的数据类型已经是 DATE。

于 2012-07-15T03:44:58.630 回答
0

更改AND stock_allocation.IDAND stock_allocation.product_ID

于 2012-07-15T03:06:09.367 回答
0

不应该是stock_allocation.product_ID = '3'代替stock_allocation.ID = '3'。stock_allocation.ID 将始终是唯一的,您将只有 1 个值为“3”的条目

于 2012-07-15T03:09:32.397 回答