我正在尝试制作一个可打印的页面,其中包含指定制造商的所有销售,列出指定日期之间的所有产品。如果没有任何销售,则应显示0。
表格
// Manufacturer table
// mid, manufacturer
// Products table
// pid, product, ref_manufacturer_id
// Orders table
// oid, orderPrice, orderDateTime, ref_product_id
有效的查询(没有日期限制)
SELECT prod.product, COALESCE(COUNT(pord.oid),0) AS orderCount,
COALESCE(SUM(pord.orderPrice),0) AS orderSum
FROM product_manufacturer AS manu
JOIN product_list AS prod ON prod.ref_manufacturer_id = manu.mid
LEFT JOIN product_orders AS pord ON pord.ref_product_id = prod.pid
WHERE manu.mid = :manu_id
GROUP BY prod.product;
但是只要我加入WHERE-syntax这个
WHERE manu.mid = :manu_id AND DATE(pord.orderDateTime) BETWEEN :orders_start AND :orders_end
我在连接和验证manu_id是int并且orders_start / end转换为MySQL日期格式时使用PHP PDO。
但我试图解决的问题是,导致问题的原因是,当我添加日期限制时,每个未订购的产品都不会显示在输出中?
创建表的SQL
CREATE TABLE product_list (
pid bigint(20) unsigned NOT NULL AUTO_INCREMENT,
product varchar(255) NOT NULL,
ref_manufacturer_id bigint(20) unsigned NOT NULL,
PRIMARY KEY (pid),
KEY ref_manufacturer_id (ref_manufacturer_id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE product_manufacturer (
mid bigint(20) unsigned NOT NULL AUTO_INCREMENT,
manufacturer varchar(255) NOT NULL,
PRIMARY KEY (mid),
UNIQUE KEY manufacturer (manufacturer)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE product_orders (
oid bigint(20) unsigned NOT NULL AUTO_INCREMENT,
orderPrice float(10,2) NOT NULL,
orderDatetime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
red_product_id bigint(20) unsigned NOT NULL,
PRIMARY KEY (oid),
KEY red_product_id (red_product_id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
答案 0 :(得分:2)
尝试:
SELECT p.product,
COALESCE(o.orderCount, 0) as orderCount,
COALESCE(o.orderSum,0) AS orderSum
FROM product_manufacturer AS m
JOIN product_list AS p ON p.ref_manufacturer_id = m.mid
LEFT JOIN (
SELECT ref_product_id as pid, COUNT(oid) AS orderCount, SUM(orderPrice) AS orderSum
FROM product_orders
WHERE DATE(orderDateTime) BETWEEN :orders_start AND :orders_end
GROUP BY ref_product_id
) AS o ON p.pid = o.pid
WHERE m.mid = :manu_id
修改:在ypercube评论后更正。
答案 1 :(得分:2)
您需要将orderDateTime
条件移动到join子句而不是where子句:
SELECT prod.product, COALESCE(COUNT(pord.oid),0) AS orderCount,
COALESCE(SUM(pord.orderPrice),0) AS orderSum
FROM product_manufacturer AS manu
JOIN product_list AS prod ON prod.ref_manufacturer_id = manu.mid
LEFT JOIN product_orders AS pord
ON pord.ref_product_id = prod.pid
AND DATE(pord.orderDateTime) BETWEEN :orders_start AND :orders_end
WHERE manu.mid = :manu_id
GROUP BY prod.product;
它在WHERE
子句中不起作用的原因是由于外连接返回的NULL
值。如果产品的product_orders
中没有行,则外部联接会为日期字段orderDateTime
返回NULL,并且该行将被过滤掉,因为NULL
不等于任何东西。
答案 2 :(得分:0)
在where子句上尝试这个。
WHERE manu.mid = :manu_id AND (DATE(pord.orderDateTime) BETWEEN :orders_start AND :orders_end)
它可能正在读取第二个AND函数作为另一个where子句,该语句应该返回true。只是预感。如果这样做,请告诉我。
答案 3 :(得分:0)
我不知道您的特定系统是如何工作的,但可能orderDateTime
未设置(即NULL
或其他内容),直到该产品被订购为止。您可以尝试:
WHERE manu.mid = :manu_id AND ((DATE(pord.orderDateTime) BETWEEN :orders_start AND :orders_end) OR pord.orderDateTime=NULL)
如果不是这种情况,你能举例说明你想要的东西没有显示的orderDateTime
值吗?