HAVING vs WHERE vs GROUP BY 子句,何时使用它们以及是否使用 ' '
HAVING vs WHERE vs GROUP BY clauses, when to use them and if you use ' '
希望这个 post 能帮助我和许多像我一样的人更好地理解 WHERE、HAVING、GROUP BY 等问题。每个人都有自己的语法处理方式,因为有不止一种方法可以让一些东西在 MYSQL 中发挥作用 我的想法是帮助我完成这项工作,同时也帮助整个社区 :) 下面是一种设计我的查询的建议方法。
SELECT t1.post_id, t2.name,
MAX(case when meta_key = 'value' THEN `meta_value` ELSE NULL END) as Email,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as CustomerId,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as DeliveryDate,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as DeliveryTime,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as DeliveryType,
MAX(case when meta_key = 'value' THEN `meta_value` ELSE NULL END) as Zip,
MAX(case when meta_key = 'value' THEN `meta_value` ELSE NULL END) as OrderNote,
MAX(case when meta_key = 'value' THEN `meta_value` ELSE NULL END) as PaymentTotal,
MAX(case when meta_key = 'value' THEN `meta_value` ELSE NULL END) as OrderStatus
FROM table_A t1
inner join table_B t2 on find_in_set(t1.post_id, t2.payment_ids)
where OrderStatus rlike '%trans%|ready'
and DeliveryDate >= current_date - interval 7 day
and DeliveryType = 'pickup'
group by
t1.post_id,
t2.name
这会产生错误 >>>>“#1054 - 'where clause' 中的未知列 'DeliveryDate'” 我认为它会产生此错误,因为“orderStatus”不是实际的列名,而是一个从另一列中提取值,然后通过 :
使其成为自己的列
MAX(case when meta_key = '_order_status' THEN `meta_value` ELSE NULL END) as OrderStatus
所以我推测我需要在语句的 SELECT 区域和 WHERE 区域中将名称括在 ' ' 中。但是会产生错误 >>>>>>>>>>>>“警告:#1292 截断不正确的日期值:'DeliveryDate'”
为什么会这样,解决方案是什么?
EDITING Because some have suggested the WHERE clause can not be used in the manner above, I have used the HAVING clause using the code below. Here is the code:
SELECT.......^^自上图......
FROM table_A t1
inner join table_B t2 on find_in_set(t1.post_id, t2.payment_ids)
GROUP BY post_id
HAVING DeliveryDate = (DATE_SUB(CURDATE(), INTERVAL 7 DAY))
AND DeliveryType = 'pickup'
AND OrderStatus = 'ready'
OR OrderStatus = 'transit'
ORDER BY 'DeliveryTime' DESC
以上也不行。这里的问题是 AND 子句更重要并且似乎会排除日期过滤器。当我使用此代码时,这 returns 所有记录,无论日期如何。
编辑 2 >>>>>>>>>> 也试过了,但它仍然没有过滤掉 3 个月前的条目
SELECT.......^^自上图......
FROM table_A t1
inner join table_B t2 on find_in_set(t1.post_id, t2.payment_ids)
GROUP BY post_id
HAVING MAX(CASE WHEN 'meta_key' = 'value' THEN 'meta_value' ELSE NULL END)>= current_date - interval 7 day
AND DeliveryType = 'pickup'
AND OrderStatus = 'ready'
OR OrderStatus = 'transit'
ORDER BY 'DeliveryTime' DESC
编辑 3 >>>>>>>>>> 简化代码。同样的结果。即使使用 CURDATE() 仍然显示 3 个月前的记录
............................
FROM table_A t1
inner join table_B t2 on find_in_set(t1.post_id, t2.payment_ids)
GROUP BY post_id
HAVING MAX(CASE WHEN 'meta_key' = 'value' THEN 'meta_value' ELSE NULL END)= CURDATE()
AND DeliveryType = 'pickup'
AND OrderStatus = 'ready'
OR OrderStatus = 'transit'
ORDER BY 'DeliveryTime' DESC
编辑 4 >>>>>>>>>>>>>>>>>>>>>>>>
最小的例子...
SELECT t1.post_id, t2.name,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as DeliveryDate,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as DeliveryTime,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as DeliveryType,
MAX(case when meta_key = 'value' THEN `meta_value` ELSE NULL END) as OrderStatus
FROM table_A t1
inner join table_B t2 on find_in_set(t1.post_id, t2.payment_ids)
GROUP BY post_id
HAVING MAX(CASE WHEN 'meta_key' = 'value' THEN 'meta_value' ELSE NULL END)= CURDATE()
AND DeliveryType = 'pickup'
AND OrderStatus = 'ready'
OR OrderStatus = 'transit'
ORDER BY 'DeliveryTime' DESC
我希望这 return 只有今天的记录。 IT 是 return 所有时间的所有记录,同时满足其他 HAVING 子句要求
您需要了解如何mysql理解查询以及如何mysql执行它。
https://qxf2.com/blog/mysql-query-execution/
When you execute a SQL query, the order in which the SQL directives
get executed is:
- FROM clause
- WHERE clause
- GROUP BY clause
- HAVING clause
- SELECT clause
- ORDER BY clause
也就是说,首先 mysql 将评估 FROM 和 Join 子句,然后是 WHERE 子句,它将从 FROM/JOIN 子句中过滤数据集。
过滤完成后,它将根据 GROUP BY 子句对数据进行分组,并且只保留满足 HAVING 子句的数据。之后,它评估 SELECT 子句并按您想要的顺序排序。
对于您的问题,您尝试使用已在 select 子句中定义的字段 (DeliveryDate) 作为过滤器。
尝试 HAVING MAX(CASE WHEN 'meta_key' = 'value' THEN 'meta_value' ELSE NULL END) >= current_date - 间隔 7 天而不是将“DeliveryDate > = current_date - where 子句中的间隔 7 天"
WHERE 子句不能在同一查询中引用列别名这一点是正确的。
这样想:
满足查询的第一步是从 FROM、JOIN 和 ON 子句构造一个虚拟 table。
第二步是根据 WHERE 子句筛选虚拟 table。
第三步是减少虚拟 table 如果需要,根据 GROUP BY 和聚合函数(SUM、COUNT、GROUP_CONCAT 等)
然后,如有必要,HAVING 基于减少的数据进行过滤。 (例如HAVING COUNT(*) > 1
。)
然后,SELECT 子句使用别名从查询中选择、计算和命名 return 的列。
最后 ORDER BY 子句进行排序操作。
因此,当查询规划器执行 WHERE 过滤时,SELECT 子句中的别名和计算列值尚未在范围内。
解决方案是将一个查询嵌套在另一个查询中,如下所示:
SELECT q.* FROM (
SELECT a, b, c AS number
FROM tbl
WHERE whatever ) q
WHERE q.number > 2
别名或内部查询在外部查询的 WHERE 子句的范围内。
这种查询模式很常见,查询优化器会尽可能高效地处理它们。
并且,您 运行 与 wp_postmeta 将每个值表示为文本字符串的方式的限制相冲突。如果要对这样的值进行日期运算,请先使用 STR_TO_DATE()。
@O 的回答。 Jones 是一个嵌套查询:
SELECT post_id
, name
, Email
, CustomerId
, DeliveryDate
, DeliveryTime
, DeliveryType
, Zip
, OrderNote
, PaymentTotal
, OrderStatus
FROM ( SELECT t1.post_id
, t2.name
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as Email
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as CustomerId
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as DeliveryDate
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as DeliveryTime
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as DeliveryType
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as Zip
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as OrderNote
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as PaymentTotal
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as OrderStatus
FROM table_A t1
INNER
JOIN table_B t2
ON FIND_IN_SET(t1.post_id, t2.payment_ids)
GROUP
BY t1.post_id
, t2.name
) AS derived_table
WHERE OrderStatus RLIKE '%trans%|ready'
AND DeliveryDate >= CURRENT_DATE - INTERVAL 7 DAY
AND DeliveryType = 'pickup'
希望这个 post 能帮助我和许多像我一样的人更好地理解 WHERE、HAVING、GROUP BY 等问题。每个人都有自己的语法处理方式,因为有不止一种方法可以让一些东西在 MYSQL 中发挥作用 我的想法是帮助我完成这项工作,同时也帮助整个社区 :) 下面是一种设计我的查询的建议方法。
SELECT t1.post_id, t2.name,
MAX(case when meta_key = 'value' THEN `meta_value` ELSE NULL END) as Email,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as CustomerId,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as DeliveryDate,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as DeliveryTime,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as DeliveryType,
MAX(case when meta_key = 'value' THEN `meta_value` ELSE NULL END) as Zip,
MAX(case when meta_key = 'value' THEN `meta_value` ELSE NULL END) as OrderNote,
MAX(case when meta_key = 'value' THEN `meta_value` ELSE NULL END) as PaymentTotal,
MAX(case when meta_key = 'value' THEN `meta_value` ELSE NULL END) as OrderStatus
FROM table_A t1
inner join table_B t2 on find_in_set(t1.post_id, t2.payment_ids)
where OrderStatus rlike '%trans%|ready'
and DeliveryDate >= current_date - interval 7 day
and DeliveryType = 'pickup'
group by
t1.post_id,
t2.name
这会产生错误 >>>>“#1054 - 'where clause' 中的未知列 'DeliveryDate'” 我认为它会产生此错误,因为“orderStatus”不是实际的列名,而是一个从另一列中提取值,然后通过 :
使其成为自己的列MAX(case when meta_key = '_order_status' THEN `meta_value` ELSE NULL END) as OrderStatus
所以我推测我需要在语句的 SELECT 区域和 WHERE 区域中将名称括在 ' ' 中。但是会产生错误 >>>>>>>>>>>>“警告:#1292 截断不正确的日期值:'DeliveryDate'”
为什么会这样,解决方案是什么?
EDITING Because some have suggested the WHERE clause can not be used in the manner above, I have used the HAVING clause using the code below. Here is the code:
SELECT.......^^自上图......
FROM table_A t1
inner join table_B t2 on find_in_set(t1.post_id, t2.payment_ids)
GROUP BY post_id
HAVING DeliveryDate = (DATE_SUB(CURDATE(), INTERVAL 7 DAY))
AND DeliveryType = 'pickup'
AND OrderStatus = 'ready'
OR OrderStatus = 'transit'
ORDER BY 'DeliveryTime' DESC
以上也不行。这里的问题是 AND 子句更重要并且似乎会排除日期过滤器。当我使用此代码时,这 returns 所有记录,无论日期如何。
编辑 2 >>>>>>>>>> 也试过了,但它仍然没有过滤掉 3 个月前的条目
SELECT.......^^自上图......
FROM table_A t1
inner join table_B t2 on find_in_set(t1.post_id, t2.payment_ids)
GROUP BY post_id
HAVING MAX(CASE WHEN 'meta_key' = 'value' THEN 'meta_value' ELSE NULL END)>= current_date - interval 7 day
AND DeliveryType = 'pickup'
AND OrderStatus = 'ready'
OR OrderStatus = 'transit'
ORDER BY 'DeliveryTime' DESC
编辑 3 >>>>>>>>>> 简化代码。同样的结果。即使使用 CURDATE() 仍然显示 3 个月前的记录
............................
FROM table_A t1
inner join table_B t2 on find_in_set(t1.post_id, t2.payment_ids)
GROUP BY post_id
HAVING MAX(CASE WHEN 'meta_key' = 'value' THEN 'meta_value' ELSE NULL END)= CURDATE()
AND DeliveryType = 'pickup'
AND OrderStatus = 'ready'
OR OrderStatus = 'transit'
ORDER BY 'DeliveryTime' DESC
编辑 4 >>>>>>>>>>>>>>>>>>>>>>>> 最小的例子...
SELECT t1.post_id, t2.name,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as DeliveryDate,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as DeliveryTime,
MAX(CASE WHEN `meta_key` = 'value' THEN `meta_value` ELSE NULL END) as DeliveryType,
MAX(case when meta_key = 'value' THEN `meta_value` ELSE NULL END) as OrderStatus
FROM table_A t1
inner join table_B t2 on find_in_set(t1.post_id, t2.payment_ids)
GROUP BY post_id
HAVING MAX(CASE WHEN 'meta_key' = 'value' THEN 'meta_value' ELSE NULL END)= CURDATE()
AND DeliveryType = 'pickup'
AND OrderStatus = 'ready'
OR OrderStatus = 'transit'
ORDER BY 'DeliveryTime' DESC
我希望这 return 只有今天的记录。 IT 是 return 所有时间的所有记录,同时满足其他 HAVING 子句要求
您需要了解如何mysql理解查询以及如何mysql执行它。
https://qxf2.com/blog/mysql-query-execution/
When you execute a SQL query, the order in which the SQL directives get executed is:
- FROM clause
- WHERE clause
- GROUP BY clause
- HAVING clause
- SELECT clause
- ORDER BY clause
也就是说,首先 mysql 将评估 FROM 和 Join 子句,然后是 WHERE 子句,它将从 FROM/JOIN 子句中过滤数据集。
过滤完成后,它将根据 GROUP BY 子句对数据进行分组,并且只保留满足 HAVING 子句的数据。之后,它评估 SELECT 子句并按您想要的顺序排序。
对于您的问题,您尝试使用已在 select 子句中定义的字段 (DeliveryDate) 作为过滤器。
尝试 HAVING MAX(CASE WHEN 'meta_key' = 'value' THEN 'meta_value' ELSE NULL END) >= current_date - 间隔 7 天而不是将“DeliveryDate > = current_date - where 子句中的间隔 7 天"
WHERE 子句不能在同一查询中引用列别名这一点是正确的。
这样想:
满足查询的第一步是从 FROM、JOIN 和 ON 子句构造一个虚拟 table。
第二步是根据 WHERE 子句筛选虚拟 table。
第三步是减少虚拟 table 如果需要,根据 GROUP BY 和聚合函数(SUM、COUNT、GROUP_CONCAT 等)
然后,如有必要,HAVING 基于减少的数据进行过滤。 (例如HAVING COUNT(*) > 1
。)
然后,SELECT 子句使用别名从查询中选择、计算和命名 return 的列。
最后 ORDER BY 子句进行排序操作。
因此,当查询规划器执行 WHERE 过滤时,SELECT 子句中的别名和计算列值尚未在范围内。
解决方案是将一个查询嵌套在另一个查询中,如下所示:
SELECT q.* FROM (
SELECT a, b, c AS number
FROM tbl
WHERE whatever ) q
WHERE q.number > 2
别名或内部查询在外部查询的 WHERE 子句的范围内。
这种查询模式很常见,查询优化器会尽可能高效地处理它们。
并且,您 运行 与 wp_postmeta 将每个值表示为文本字符串的方式的限制相冲突。如果要对这样的值进行日期运算,请先使用 STR_TO_DATE()。
@O 的回答。 Jones 是一个嵌套查询:
SELECT post_id
, name
, Email
, CustomerId
, DeliveryDate
, DeliveryTime
, DeliveryType
, Zip
, OrderNote
, PaymentTotal
, OrderStatus
FROM ( SELECT t1.post_id
, t2.name
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as Email
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as CustomerId
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as DeliveryDate
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as DeliveryTime
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as DeliveryType
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as Zip
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as OrderNote
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as PaymentTotal
, MAX(CASE WHEN meta_key = 'value' THEN meta_value ELSE NULL END) as OrderStatus
FROM table_A t1
INNER
JOIN table_B t2
ON FIND_IN_SET(t1.post_id, t2.payment_ids)
GROUP
BY t1.post_id
, t2.name
) AS derived_table
WHERE OrderStatus RLIKE '%trans%|ready'
AND DeliveryDate >= CURRENT_DATE - INTERVAL 7 DAY
AND DeliveryType = 'pickup'