查询以获取当前值

时间:2015-11-06 13:15:33

标签: mysql sql

我有以下表格

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获得最旧的值。它应该根据当前日期取值。我怎样才能做到这一点?

2 个答案:

答案 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,因此这些字段应该已经被编入索引,这使得它的速度非常快查询。

sqlfiddle.

中查看此操作