MySQL,同时在内部和外部查询中分组

时间:2017-01-06 11:18:50

标签: mysql sql group-by aggregate-functions nested-query

有这样的SQL查询:

SELECT position, AVG(price) FROM products WHERE position IS NOT NULL
AND price < (SELECT AVG(price)+2*STDDEV(price) FROM price)
AND position = 3

如果您当时只想检查一个位置,那很好,但我有很多位置,因此我希望同时获取所有位置的数据。

即。类似的东西:

[QUERY]... GROUP BY position

但是我如何在内部和外部查询中按位置进行分组,因此内部查询where子句返回与正确位置匹配的值。

感谢。

2 个答案:

答案 0 :(得分:1)

您正在寻找GROUP BY。要获得每个职位的平均价格而不仅仅是一个职位,这就是你的工作。

SELECT position, AVG(price) average
  FROM products
GROUP BY position

您的查询中有两个sigma排除项。您需要使用相同的技术来获得每个位置的限制。如果要计算每个位置的平均值+ 2西格玛限制,则需要此子查询。 (注意:最好在SQL等语言中使用括号,而不是信任算术运算符优先级。)

                 SELECT position, 
                        AVG(price) + (2.0 * STDDEV(price)) upper_limit
                   FROM products 
                  GROUP BY position

然后,您可以将该查询加入顶级选择,如此

 SELECT a.position, a.price
   FROM products
   JOIN (
                 SELECT position, 
                        AVG(price) + (2.0 * STDDEV(price)) upper_limit
                   FROM products 
                  GROUP BY position
        ) b  ON a.position = b.position
            AND a.price < b.upper_limit

这为您提供了排除异常值的位置/价格的原始数据。您是否看到ON子句如何按位置匹配主和子查询中的行,然后过滤掉原始价格高于upper_limit的行?这就是诀窍。

然后,您可以使用典型的GROUP BY汇总该数据。

 SELECT a.position, AVG(a.price) average
   FROM products
   JOIN (
                 SELECT position, 
                        AVG(price) + (2.0 * STDDEV(price)) upper_limit
                   FROM products 
                  GROUP BY position
        ) b  ON a.position = b.position
            AND a.price < b.upper_limit
  GROUP BY a.position

查询中的子查询分层是它被称为结构化查询语言的原因。

答案 1 :(得分:0)

不添加GROUP BY可以达到你想要的效果吗?

SELECT position, AVG(price)
FROM products p
WHERE position IS NOT NULL AND
      price < (SELECT AVG(price)+2*STDDEV(price)
               FROM price p2
              ) 
GROUP BY position;

或者,您关心的是某种特定产品吗?如果是这样,您需要一个相关的子查询:

SELECT position, AVG(price)
FROM products p
WHERE position IS NOT NULL AND
      price < (SELECT AVG(price)+2*STDDEV(price)
               FROM price p2
               WHERE p.? = p2.?
              ) 
GROUP BY position;

目前还不清楚应该使用哪个列进行关联。