数据库架构:
DROP TABLE IF EXISTS salespersons, orders, orderlines, products;
CREATE TABLE salespersons(salespersonid INT,NAME CHAR(8));
INSERT INTO salespersons VALUES(1,'Sam'),(2,'Xavier');
CREATE TABLE orders(orderid INT,salespersonid INT);
INSERT INTO orders VALUES(1,1),(2,1),(3,1),(4,2),(5,2);
CREATE TABLE orderlines(lineid INT,orderid INT,productid INT,qty INT);
INSERT INTO orderlines VALUES(1,1,1,1),(2,1,1,2),(3,2,2,1),(4,3,1,1),(5,4,1,1),(6,5,2,2);
CREATE TABLE products(productid INT,NAME CHAR(32));
INSERT INTO products VALUES(1,'computer desk'),(2,'lamp'),(3,'desk chair');
问题:
想要检索产品清单,即所有卖家销售的产品。
预期产出:
我创建了以下查询
SELECT
p1.`name` AS productList
FROM
`products` AS p1
LEFT JOIN
(SELECT
p.`productid`,
COUNT(DISTINCT (s.`salespersonid`)) AS productSellers,
(SELECT
COUNT(*)
FROM
salespersons) AS totalSeller
FROM
`products` AS p
INNER JOIN orderlines AS ol
ON p.`productid` = ol.`productid`
INNER JOIN orders AS o
ON ol.`orderid` = o.`orderid`
INNER JOIN salespersons AS s
ON o.`salespersonid` = s.`salespersonid`
GROUP BY p.`productid`
HAVING productSellers = totalSeller) AS ps
ON p1.`productid` = ps.productid
WHERE ps.productid IS NOT NULL;
它给出了正确的结果,但我不确定它是否为这样的问题编写查询的标准方式。
如果有人知道更好的方式来撰写此问题的查询,请建议
答案 0 :(得分:2)
你的基本方法很好。您正在比较销售产品的销售人员数量与销售人员总数。但是,您的查询可以简化:
SELECT p.Name
FROM products p INNER JOIN
orderlines ol
ON p.productid = ol.productid INNER JOIN
orders o
ON ol.orderid = o.orderid
GROUP BY p.name
HAVING COUNT(DISTINCT o.salespersonid) = (SELECT COUNT(*) FROM salespersons);
以下是更改:
products
的额外加入。所有工作都在子查询中完成,只需返回您想要的值。SalesPerson
表(除非o.SalesPersonId
可能无效)。您可以从orders
。HAVING
子句中,而不是使用列别名。作为优先选择,我还从表别名中删除了反引号和as
。我发现反引号使查询更难阅读。我只使用(并且总是)使用as
作为列别名但发现表别名不需要它们。
答案 1 :(得分:1)
您可以删除几个连接,因为它们似乎是不必要的
SELECT
p1.`name` AS productList
FROM
`products` AS p1
LEFT JOIN
(SELECT
ol.`productid`,
COUNT(DISTINCT (o.`salespersonid`)) AS productSellers,
(SELECT
COUNT(*)
FROM
salespersons) AS totalSeller
FROM
orderlines AS ol
INNER JOIN orders AS o
ON ol.`orderid` = o.`orderid`
GROUP BY ol.`productid`
HAVING productSellers = totalSeller) AS ps
ON p1.`productid` = ps.productid
WHERE ps.productid IS NOT NULL;
这是一个SQLFiddle - http://www.sqlfiddle.com/#!2/4aa66/5
除此之外,如果您需要更好的性能,只需在有意义的地方添加索引。一个好的起点就是你要加入的列,但是理解这可能会在更新/插入/删除记录时造成额外的开销。