Mysql查询以下要求

时间:2014-04-20 14:42:13

标签: mysql

数据库架构:

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');
  

问题:

想要检索产品清单,即所有卖家销售的产品。

预期产出:

enter image description here

我创建了以下查询

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;

它给出了正确的结果,但我不确定它是否为这样的问题编写查询的标准方式。

如果有人知道更好的方式来撰写此问题的查询,请建议

2 个答案:

答案 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

除此之外,如果您需要更好的性能,只需在有意义的地方添加索引。一个好的起点就是你要加入的列,但是理解这可能会在更新/插入/删除记录时造成额外的开销。