关闭ONLY_FULL_GROUP_BY是个好主意吗?

时间:2019-01-24 11:37:13

标签: mysql mariadb

我想获得“订单”表中而不是“客户”表中的客户。 “快速订购”的客户。我写了这个查询:

SELECT `email`, `firstname` , `lastname`, `telephone`, `ip`, NULL
FROM `order`
WHERE `customer_id` = 0 AND `email` NOT IN (SELECT `email` FROM `ocustomer`)
GROUP BY `email`

但是我得到了:

  

SELECT列表包含非聚合列(名字,姓氏,电话,ip),这是不兼容的   使用sql_mode = only_full_group_by

我在这里有两个选择:

  1. 关闭ONLY_FULL_GROUP_BY。我知道该怎么做,但这是个好主意吗?我知道这很有用,但就我而言,如果将其打开,我需要重写查询
  2. 使用ANY_VALUE(),但不适用于MariaDb。另一方面,我不能使用聚合函数,因为我有文本字段。因此,我不知道要在这里使用ONLY_FULL_GROUP_BY进行其他更改。

我很困惑该怎么办?关闭ONLY_FULL_GROUP_BY是个好主意,还是有另一种不用ANY_VALUE()重写查询的方法?

2 个答案:

答案 0 :(得分:0)

关闭它不是一个好主意。它可以帮助您避免会导致错误查询结果的错误。

您可以这样编写查询:

SELECT `email`, `firstname` , `lastname`, `telephone`, `ip`, NULL
FROM `order`
WHERE `customer_id` = 0 AND `email` NOT IN (SELECT `email` FROM `ocustomer`)
GROUP BY `email`, `firstname` , `lastname`, `telephone`, `ip`

当每封电子邮件中有多行具有不同的值时,您仍然可以使用聚合函数。不是总和或计数,而是最小和最大工作量。

SELECT `email`, MIN(`firstname`) AS firstname , MIN(`lastname`) AS lastname, /* ... you get the idea */
FROM `order`
WHERE `customer_id` = 0 AND `email` NOT IN (SELECT `email` FROM `ocustomer`)
GROUP BY `email`

答案 1 :(得分:0)

请勿使用NOT IN ( SELECT ... )。在这种情况下,它的性能很差,并且无法按您需要的方式工作。使用LEFT JOIN

SELECT  DISTINCT
        o.`email`, o.`firstname`, o.`lastname`, o.`telephone`,
        o.`ip`, NULL
    FROM  `order` AS o
    LEFT JOIN  ocustomer AS oc USING(email)
    WHERE  o.`customer_id` = 0
      AND  oc.email IS NULL

有益:

 order:     INDEX(customer_id)
 ocustomer: INDEX(email)

这可能更好,尤其是因为它像您对问题的陈述那样“读”起来:

SELECT  DISTINCT
        o.`email`, o.`firstname`, o.`lastname`, o.`telephone`,
        o.`ip`, NULL
    FROM  `order` AS o
    WHERE  o.`customer_id` = 0
      AND  NOT EXISTS( SELECT 1 FROM ocustomer WHERE email = o.email )

使用DISTINCT代替几乎等效的GROUP BY

  • 它避免了错误消息。
  • 它将显示该电子邮件是否与多个姓名,电话等相关联。

(注意:与流行观点相反,SELECT DISTINCT(a), b ...并不只是a的“独特之处”。)