在这种特定情况下,如何使用 SQL 仅检索与日期字段的最后一个值相关的记录?

Posted

技术标签:

【中文标题】在这种特定情况下,如何使用 SQL 仅检索与日期字段的最后一个值相关的记录?【英文标题】:How can I retrieve only the record related to the last value of a date field in this specific case using SQL? 【发布时间】:2017-12-18 14:09:20 【问题描述】:

我不是很喜欢数据库,我在尝试修改 mysql 上定义的查询时发现了一些问题。

我有这个查询是我的起始点(必须修改的查询):

SELECT
    MC_PS.id                                            AS price_series_id,
    MC_PS.market_commodity_details_id                   AS market_commodity_details_id,
    MC_PS.price_date                                    AS price_date,
    MC_PS.avg_price                                     AS avg_price,
    CU.ISO_4217_cod                                     AS currency,
    MU.unit_name                                        AS measure_unit,
    MD_CD.market_details_id                             AS market_id,
    MD_CD.commodity_details_id                          AS commodity_id

    FROM Market_Commodity_Price_Series AS MC_PS

    INNER JOIN MeasureUnit AS MU
        ON MC_PS.measure_unit_id = MU.id

    INNER JOIN Currency AS CU
        ON MC_PS.currency_id = CU.id

    INNER JOIN MarketDetails_CommodityDetails AS MD_CD
          ON MC_PS.market_commodity_details_id = MD_CD.id

此查询返回某个市场中某些商品的价格,这是查询输出:

price_series_id      market_commodity_details_id price_date      avg_price            currency measure_unit       market_id            commodity_id        
-----------------------------------------------------------------------------------------------------------------------------------------------------
17                   25                          18/12/2017      778                  RWF      kilogram           4                    6                   
70                   32                          17/12/2017      5                    RWF      kilogram           6                    16                  
71                   32                          18/12/2017      6                    RWF      kilogram           6                    16                  
3                    26                          15/12/2017      12,84                XOF      kilogram           4                    8                   
4                    25                          15/12/2017      18,233               XOF      kilogram           4                    6                   
5                    25                          16/12/2017      22,84                XOF      kilogram           4                    6                   
6                    24                          16/12/2017      18,94                XOF      kilogram           4                    4                   
7                    24                          17/12/2017      28,63                XOF      kilogram           4                    4                   
9                    26                          18/12/2017      48,37                XOF      kilogram           4                    8                   
11                   24                          18/12/2017      33,33                XOF      kilogram           4                    4                   
18                   28                          18/12/2017      13,7                 XOF      kilogram           5                    4                   
19                   28                          17/12/2017      16,2                 XOF      kilogram           5                    4                   
20                   28                          16/12/2017      14,9                 XOF      kilogram           5                    4                   
21                   30                          18/12/2017      21,47                XOF      kilogram           5                    3                   
22                   30                          16/12/2017      22,39                XOF      kilogram           5                    3                   
23                   30                          17/12/2017      23,17                XOF      kilogram           5                    3                   
24                   26                          17/12/2017      16,22                XOF      kilogram           4                    8                   
26                   26                          16/12/2017      19,39                XOF      kilogram           4                    8                   
27                   31                          18/12/2017      13,2                 XOF      kilogram           5                    8                   
28                   31                          17/12/2017      14,4                 XOF      kilogram           5                    8                   
29                   31                          16/12/2017      12,6                 XOF      kilogram           5                    8                   
31                   25                          17/12/2017      17,8                 XOF      kilogram           4                    6                   
32                   25                          17/12/2017      14,8                 XOF      kilogram           4                    6                   
33                   29                          18/12/2017      8,2                  XOF      kilogram           5                    1                   
34                   29                          17/12/2017      9,6                  XOF      kilogram           5                    1                   
35                   29                          16/12/2017      9,3                  XOF      kilogram           5                    1                

如您所见,它包含特定日期(price_date)在市场 (ma​​rket_id) 中销售的商品 (commodity_id) 的价格>)。

我需要修改我的查询,只显示市场上出售的商品的最后价格。

实际上,如果在之前的结果中有多个记录与在特定市场上销售的特定商品相关的不同日期,则必须返回最后一个日期的单个记录。

所以我修改后的查询的输出必须是这样的:

price_series_id      market_commodity_details_id price_date      avg_price            currency measure_unit       market_id            commodity_id        
-----------------------------------------------------------------------------------------------------------------------------------------------------            
71                   32                          18/12/2017      6                    RWF      kilogram           6                    16                                  
9                    26                          18/12/2017      48,37                XOF      kilogram           4                    8                  
11                   24                          18/12/2017      33,33                XOF      kilogram           4                    4                 
18                   28                          18/12/2017      13,7                 XOF      kilogram           5                    4                                    
21                   30                          18/12/2017      21,47                XOF      kilogram           5                    3                                                    
27                   31                          18/12/2017      13,2                 XOF      kilogram           5                    8                                 
17                   25                          18/12/2017      778                  RWF      kilogram           4                    6                  
33                   29                          18/12/2017      8,2                  XOF      kilogram           5                    1                   

正如您所见,每个 ma​​rket_idcommodity_id 字段仅检索与最后一个 price_date 值相关的记录

如何正确实施此更改?

也许我可以以某种方式将 GROUP BYHAVING 子句一起使用?

【问题讨论】:

【参考方案1】:

您的Market_Commodity_Price_Series 表是否有一个自动递增的id 列?您的应用程序是否总是在 INSERT 新行中添加最近的 price_date 值?

如果是这样,您可以在查询中添加 WHERE 子句,如下所示

WHERE MC_PS.id IN  ( SELECT MAX(id) id 
                       FROM Market_Commodity_Price_Series
                      GROUP BY market_commodity_details_id )

这将过滤除每个项目的最高 id 值之外的所有值。如果假设为真,那也将是最新值。

如果这些假设不成立,您可以使用类似的过滤器,但难度更大。要获取每个项目的最新 id 值,请执行以下操作:

           SELECT a.id
             FROM Market_Commodity_Price_Series a
             JOIN (
                     SELECT MAX(price_date) price_date,
                            market_commodity_details_id 
                       FROM Market_Commodity_Price_Series 
                      GROUP BY market_commodity_details_id 
                  ) b ON a.market_commodity_details_id = b.market_commodity_details_id 
                     AND a.price_date = b.price_date

此查询查看您的表格并查找每个项目的最新日期。然后它恢复该项目的id 值。然后,您可以在 WHERE id IN () 子句中使用整个子查询,如上所示。

【讨论】:

我将反对票改为赞成票。使用 O Jones 第二种解决方案。第一个不是一个好主意恕我直言 如果前提条件成立(自动递增 ID,没有更新,只有插入,并且每次插入都使用当前日期,我的第一个解决方案是正确的并且确实执行得非常好,尽管有相反的意见。它也正确如果有多个重复的最新日期值,则消除歧义。【参考方案2】:

哦。琼斯的第一个想法不是一个好主意。使用子查询获取最新日期的记录并加入该记录。这是未经测试的,但请查看最后一次加入

SELECT
    MC_PS.id                                            AS price_series_id,
    MC_PS.market_commodity_details_id                   AS     market_commodity_details_id,
    MC_PS.price_date                                    AS price_date,
    MC_PS.avg_price                                     AS avg_price,
    CU.ISO_4217_cod                                     AS currency,
    MU.unit_name                                        AS measure_unit,
    MD_CD.market_details_id                             AS market_id,
    MD_CD.commodity_details_id                          AS commodity_id

FROM Market_Commodity_Price_Series AS MC_PS

INNER JOIN MeasureUnit AS MU
    ON MC_PS.measure_unit_id = MU.id

INNER JOIN Currency AS CU
    ON MC_PS.currency_id = CU.id

INNER JOIN MarketDetails_CommodityDetails AS MD_CD
      ON MC_PS.market_commodity_details_id = MD_CD.id

INNER JOIN 
(SELECT id , MAX(price_date) as price_date
    FROM Market_Commodity_Price_Series 
    GROUP BY id) b on MC_PS.id = b.id AND MC_PS.price_date = b.price_date

【讨论】:

以上是关于在这种特定情况下,如何使用 SQL 仅检索与日期字段的最后一个值相关的记录?的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL 中出现特定文本字符串时检索行

仅使用特定 c_id 检索发送者数据的 Sql 查询,其中发送者和接收者数据在同一个表中

如何在不使用 Pandas 的情况下创建等效于 numpy.nan 的日期时间对象?

ORACLE PL/SQL - 使用 SYSDATE 检索特定日期的数据时出现检索问题

如何在没有一年的情况下检索从 Google 通讯录同步的联系人事件?

如何在没有插件的情况下从特定类别的帖子的 URL 中删除日期?