我有以下表格
menu_supp
menu_id supp_id supp_weight supp_load_follow
1 29 10.00 1
1 31 20.00 2
supps
supp_id user_id supp_name
29 1 Test supp 1
31 1 Test supp 2
supps_prop
supp_id supp_dry_w supp_price supp_date
29 95.00 125.00 2015-10-25
29 94.00 124.00 2015-11-06
29 94.00 128.00 2015-11-12
31 25.00 200.00 2015-06-25
现在我收到了这个问题:
SELECT s.supp_id, s.supp_name, ms.supp_weight, sp.supp_price, sp.supp_dry_weight
FROM menu_supp ms
LEFT JOIN supps s ON ms.supp_id = s.supp_id
LEFT JOIN supps_prop sp ON ms.supp_id = sp.supp_id
WHERE menu_id = 1
GROUP BY s.supp_id
ORDER BY ms.supp_load_follow ASC
这给了我这个结果:
supp_id supp_name supp_weight supp_price supp_dry_weight
29 Test supp 1 10.00 125.00 95.00
31 Test supp 2 20.00 200.00 25.00
从supp 29获得最旧的值。它应该根据当前日期取值。我怎样才能做到这一点?
答案 0 :(得分:2)
如果supp_date对于supp_id是唯一的,那么您可以使用以下内容获取最新日期的值: -
SELECT s.supp_id, s.supp_name, ms.supp_weight, sp.supp_price, sp.supp_dry_weight
FROM menu_supp ms
LEFT JOIN supps s
ON ms.supp_id = s.supp_id
LEFT JOIN
(
SELECT supp_id, MAX(supp_date) AS max_supp_date
FROM supps_prop
GROUP BY supp_id
) sub0
ON ms.supp_id = sub0.supp_id
LEFT OUTER JOIN supps_prop sp
ON sub0.supp_id = sp.supp_id
AND sub0.max_supp_date = sp.supp_date
WHERE menu_id = 1
ORDER BY ms.supp_load_follow ASC
这会获取每个supp_id的最大supp_date,并将其连接回supps_prop表以从中获取其他字段。
编辑 - 应对最高日期或今天之后的最低日期有点复杂。
我建议有2个子查询。一个获取每个supp_id的最高日期,一个获取每个supp_id的今天或之后的最低日期。如果找到第二个,那么使用它,如果不使用第一个。未经测试但是: -
SELECT s.supp_id, s.supp_name, ms.supp_weight, COALESCE(sp1.supp_price, sp0.supp_price), COALESCE(sp1.supp_dry_weight, sp0.supp_dry_weight)
FROM menu_supp ms
LEFT JOIN supps s
ON ms.supp_id = s.supp_id
LEFT JOIN
(
SELECT supp_id, MAX(supp_date) AS max_supp_date
FROM supps_prop
GROUP BY supp_id
) sub0
ON ms.supp_id = sub0.supp_id
LEFT OUTER JOIN supps_prop sp0
ON sub0.supp_id = sp0.supp_id
AND sub0.max_supp_date = sp0.supp_date
LEFT JOIN
(
SELECT supp_id, MIN(supp_date) AS max_supp_date
FROM supps_prop
WHERE supp_date >= CURDATE()
GROUP BY supp_id
) sub1
ON ms.supp_id = sub1.supp_id
LEFT OUTER JOIN supps_prop sp1
ON sub1.supp_id = sp1.supp_id
AND sub1.max_supp_date = sp1.supp_date
WHERE menu_id = 1
ORDER BY ms.supp_load_follow ASC
编辑 - GROUP BY等的解释: -
GROUP BY用于聚合函数;这些函数在一系列共享公共字段值的行上提供值。例如,SUM将用于通常为多个行添加字段的值以获得共享值(即,可能是客户ID的订单值的SUM)。共享值字段用于GROUP BY字段中。
在普通标准SQL中,SELECT语句返回的所有返回的非聚合字段必须在GROUP BY语句中提及。这有逻辑意义,好像它们没有被提及那么一组行的值可能不同,然后存在选择哪一个的问题。
然而,有时这可能有点过于严格。例如,如果您按客户ID进行分组,则客户名称与此客户ID直接相关。 MySQL允许您返回SELECT语句中未在GROUP BY子句中指定的非聚合字段,但如果值在组合在一起的行之间变化,则不指定选择哪个值;它可以来自任何行,实际上没有理由在将来或使用不同的存储引擎时不会改变。
有时候GROUP BY被滥用来返回唯一的行,就像要使用DISTINCT一样。
在原始查询中
SELECT s.supp_id,s.supp_name,ms.supp_weight,sp.supp_price, sp.supp_dry_weight FROM menu_supp ms LEFT JOIN supps s ON ms.supp_id = s.supp_id LEFT JOIN supps_prop sp ON ms.supp_id = sp.supp_id WHERE menu_id = 1 GROUP BY s.supp_id ORDER BY ms.supp_load_follow ASC
您正在使用GROUP BY s.supp_id。虽然s.supp_name依赖于此,但ms.supp_weight和sp.supp_price不是。对于任何s.supp_id,每个都可以有许多值。 MySQL刚刚使用了其中一个分组行的值,并不关心它选择使用哪一行。
答案 1 :(得分:1)
这是没有group by
并使用内部联接的查询。在我看来, supp_id 不会插入到 supps 中尚未定义的 menu_supp 中。我想在 supps_prop 中没有条目可能,但这看起来也很值得怀疑。如果我错了,只需改回来。
SELECT s.supp_id, s.supp_name, ms.supp_weight, sp.supp_price,
sp.supp_dry_w, sp.supp_date
FROM menu_supp ms
JOIN supps s
ON s.supp_id = ms.supp_id
JOIN supps_prop sp
ON sp.supp_id = ms.supp_id
WHERE menu_id = 1
ORDER BY ms.supp_load_follow;
我还添加了日期,以便更容易理解。结果都是四行:
supp_id supp_name supp_weight supp_price supp_dry_w supp_date
------- --------- ----------- ---------- ---------- ---------
29 Test supp 1 10.00 125.00 95.00 2015-10-25
29 Test supp 1 10.00 124.00 94.00 2015-11-06
29 Test supp 1 10.00 128.00 94.00 2015-11-12
31 Test supp 2 20.00 200.00 25.00 2015-06-25
显然,您只想加入包含在当前或最近日期的行中的 prop 信息。那个日期是过去仍然是最大的价值。可以这样找到:
SELECT s.supp_id, s.supp_name, ms.supp_weight, sp.supp_price,
sp.supp_dry_w, sp.supp_date
FROM menu_supp ms
JOIN supps s
ON s.supp_id = ms.supp_id
JOIN supps_prop sp
ON sp.supp_id = ms.supp_id
and sp.supp_date =(
select Max( supp_date )
from supps_prop
where supp_id = ms.supp_id
and supp_date <= NOW() )
WHERE menu_id = 1
ORDER BY ms.supp_load_follow;
不要让子查询关注你。由于 supp_id 和 supp_date 的组合是 prop 表中最明显的PK,因此这些字段应该已经被编入索引,这使得它的速度非常快查询。
中查看此操作