问题描述
希望这篇文章能帮助我和其他许多我更好地了解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子句'中的未知列'DeliveryDate'”我推测它会产生此错误,因为“ orderStatus”不是实际的列名,而是从另一个值中提取的值列,然后通过:
使其成为自己的列MAX(case when Meta_key = '_order_status' THEN `Meta_value` ELSE NULL END) as OrderStatus
因此,我想我需要在语句的SELECT区域和WHERE区域中将名称括在''中。但是会产生错误>>>>>>>>>>>>“警告:#1292日期值被截断的错误:'DeliveryDate'”
为什么会这样,怎么解决?
选择....... ^^从上方..............
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子句更重要,似乎使日期过滤器失效。当我使用此代码时,它将返回所有记录,而不考虑日期。
编辑2 >>>>>>>>>>尝试过也是如此,它仍然无法过滤出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)>= current_date - interval 7 day
AND DeliveryType = 'pickup'
AND OrderStatus = 'ready'
OR OrderStatus = 'transit'
ORDER BY 'DeliveryTime' DESC
EDIT 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 >>>>>>>>>>>>>>>>>>>>>>>> 最小的例子...
选择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 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
我希望这只会返回今天的记录。 IT会在满足其他HAVING子句要求的同时返回所有时间的所有记录
解决方法
您是正确的,WHERE子句不能引用同一查询中的列别名。
这样想:
满足查询条件的第一步是从FROM,JOIN和ON子句构造一个虚拟表。
第二步是根据WHERE子句过滤该虚拟表。
第三步是根据GROUP BY和聚合函数(SUM,COUNT,GROUP_CONCAT等),根据需要减少虚拟表
然后,如有必要,可以根据精简后的数据进行过滤。 (例如HAVING COUNT(*) > 1
。
然后,SELECT子句选择,计算并使用别名命名要从查询返回的列。
最后,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()。
,您需要了解mysql如何理解查询以及mysql如何执行查询。
https://qxf2.com/blog/mysql-query-execution/
执行SQL查询时,SQL指令的顺序 被执行的是:
- FROM子句
- WHERE子句
- GROUP BY子句
- HAVING子句
- SELECT子句
- ORDER BY子句
也就是说,首先mysql将评估FROM和Join子句,然后在WHERE子句中从FROM / JOIN子句中过滤数据集。
一旦过滤器完成,它将基于GROUP BY子句对数据进行分组,并且仅保留那些满足HAVING子句的数据。之后,它将根据您的需要评估SELECT子句和顺序。
对于您的问题,您尝试使用在select子句中定义的字段(DeliveryDate)作为过滤器。
尝试获得一个最大值(在'meta_key'='value'THEN'meta_value'ELSE NULL END的情况下)> = current_date-间隔7天,而不是在where子句中放置“ DeliveryDate> = current_date-间隔7天”
,根据@O的答案。琼斯是一个嵌套查询:
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'