繁体   English   中英

MYSQL子查询并计算包含值的行数

[英]MYSQL Subquery and count number of rows containing a value

我有两个表oc_order ooc_order_total ot

oc_order o具有字段o.customer_id, o.date_added, o.email,o.total

oc_order_total ot具有字段ot.codeot.value

我只想在客户订单超过3次的情况下显示结果,即customer_id在结果中重复三次或更多,并显示ot.value where ot.code = 'shipping'

我正在尝试跟随


SELECT COUNT(o.customer_id) AS 'Orders Count', o.date_added, o.email,o.total, ot.value
FROM oc_order o
Inner join oc_order_total ot ON ot.order_id = o.order_id
WHERE count(o.customer_id) > 3 AND ot.value = (select value from oc_order_total where code = 'shipping' )
GROUP BY o.customer_id


我正在无效使用组错误,我想我在where子句中没有正确使用子查询。

您不能在WHERE语句中使用SUM / COUNT 您需要使用此HAVING运算符。 试试这个查询:

SELECT COUNT(o.customer_id) AS 'Orders Count', o.date_added, o.email,o.total, ot.value

FROM oc_order o
INNER JOIN oc_order_total ot ON ot.order_id = o.order_id AND 

WHERE ot.code IN (select value from oc_order_total where code = 'shipping' )

GROUP BY o.customer_id
HAVING count(o.customer_id) > 3

编辑:添加示例与ot.value不受GROUP BY影响。

SELECT o.order_id, q.orders_count AS 'Orders Count', o.date_added, o.email,o.total, ot.value

FROM oc_order o
INNER JOIN oc_order_total ot ON ot.order_id = o.order_id
INNER JOIN (SELECT o.customer_id, COUNT(o.customer_id) AS orders_count

FROM oc_order o
INNER JOIN oc_order_total ot ON ot.order_id = o.order_id

WHERE ot.code IN (select value from oc_order_total where code = 'shipping' )

GROUP BY o.customer_id
HAVING count(o.customer_id) > 3) AS q ON q.customer_id = o.customer_id

基本上,这里发生的事情是您用先前的查询预先过滤了客户,然后使用这些预先过滤的列表来为这些满足您条件的客户获取单个订单。 在这个单独的orders_id您可以执行任何操作而无需分组,因为您已经淘汰了不满足需求的客户。 希望能帮助到你。

不,由于遇到错误,因为GROUP BY不包含SELECT列表中列出的所有列,并且无法使用WHERE条件下的COUNT()聚合函数; 仅在HAVING子句中允许。 您可以像这样修改查询

SELECT o.date_added
     , o.email
     , o.total
     , ot.value
  FROM oc_order o
  JOIN oc_order_total ot 
    ON ot.order_id = o.order_id
  JOIN
     ( SELECT COUNT(customer_id) AS 'Orders Count'
            , customer_id
         FROM oc_order
        GROUP 
           BY customer_id 
     ) xxx 
    ON xxx .customer_id = o.customer_id
 WHERE  xxx.`Orders Count` > 3 
   AND ot.code = 'shipping';

一方面,无法在WHERE子句中引用聚合。

访问行时将评估WHERE子句中的谓词。 在检索行时,MySQL没有有关聚合函数返回的值的任何信息(例如COUNT() )。

COUNT()的行被存取聚合将被评估,并且后GROUP BY操作。

可以在GROUP BY子句之后的HAVING子句中引用聚合。

 GROUP BY ...
HAVING COUNT(...) > 3

请注意,HAVING子句是 GROUP BY操作之后和聚合表达式的值之后进行求值的。 与WHERE子句大不相同。


而且,子查询有点奇怪。 因为在相等比较中被引用,所以子查询最多可以返回一行。 除非保证code在ot_中是唯一的,否则我们在查询中看不到任何阻止它的内容。

如果code是唯一的,那么我们根本不需要子查询,只需测试代码即可。

 WHERE ot.code = 'shipping'

如果在code列中有多行带有“装运”,则我们无法保证这些行上的value列相同。 为了测试任何可能的值,我们可以使用IN运算符代替相等(标量)比较。 例如

 WHERE ot.value IN ( SELECT v.value 
                       FROM oc_order_total v
                      WHERE v.code = 'shipping'
                   )

但这看起来仍然很奇怪。 奇怪的是,它使用的表与外部查询相同 如果我们使用子查询来查找与字符串code相关的value集合,通常是一个单独的查找表。 而且我们通常更喜欢JOIN操作而不是IN (subquery) 很奇怪。


另外,SELECT列表中的非聚合表达式

 o.date_added, o.email, o.total, ot.value

不要出现在GROUP BY子句中。 大多数关系数据库都会抛出类似错误,“在选择时不按组进行非聚合”。

但是,MySQL扩展将允许查询运行,但是为非聚合返回的值是不确定的。 MySQL将基于折叠集中包含的某些行返回这些表达式的值,但不能保证将是哪一行。

通过在sql_mode变量中包含ONLY_FULL_GROUP_BY ,我们还可以使MySQL像其他数据库一样引发错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM