【问题标题】:Group By column, returning most recent AND earliest fields按列分组,返回最近和最早的字段
【发布时间】:2017-01-11 18:12:59
【问题描述】:

我有一张桌子:

ITEM    NOTE        RECORD_DATE             USER
Apple   Blah        2016-12-30 11:22:33     mcmurphy510
Orange  Somenote    2016-12-31 11:22:33     user2
Apple   BlahBlah    2017-01-01 11:22:33     user2

我正在尝试创建一个显示项目和最新注释的查询。我还需要从 DATE 和 USER 列中导出四个字段:

CREATED: 应该是给定ITEM最早行的RECORD_DATE时间戳

CREATED_BY:对于给定的ITEM,应该是最早行的USER

UPDATED: 应该是给定ITEM最近行的RECORD_DATE时间戳

UPDATED_BY:对于给定的ITEM,应该是最近行的USER

使用以下查询,我设法获得了其中一个(最早的或最新的),但不能同时获得:

SELECT
    i.item,
    i.note,
    i.record_date AS created,
    i.user AS created_by
FROM
    item i
    INNER JOIN (
        SELECT
            item,
            MAX(record_date) as record_date
        FROM item
        GROUP BY item
    ) i2
        ON (
            i.item = i2.item AND
            i.record_date = i2.record_date
        )

使用它,我可以通过在子查询中的MAX()MIN() 之间切换来在返回最早和最近的RECORD_DATE 之间切换。

我的问题是如何创建一个可以在同一行中同时显示最早和最新结果的信号查询?

期望的结果:

ITEM    NOTE        CREATED                 CREATED_BY      UPDATED                 UPDATED_BY
Apple   BlahBlah    2016-12-30 11:22:33     mcmurphy510     2017-01-01 11:22:33     user2
Orange  Somenote    2016-12-31 11:22:33     user2           NULL                    NULL

我在这里有一个小提琴: http://sqlfiddle.com/#!9/cd724a/3

【问题讨论】:

  • 为什么橙色行不会出现两次?毕竟两者都是!!

标签: mysql group-by timestamp


【解决方案1】:

您可以找到每个项目的最早和最晚日期,然后像这样加入主表:

select
    i1.item,
    i2.note,
    i1.record_date created_date,
    i1.user create_user,
    case when i1.record_date <> i2.record_date then i2.record_date end update_date,
    case when i1.record_date <> i2.record_date then i2.user end update_user
from item i1
inner join item i2
on i1.item = i2.item
inner join (
select item, min(record_date) mn, max(record_date) mx
from item
group by item
) i3 on i1.item = i3.item
and i1.record_date = i3.mn
and i2.record_date = i3.mx;

SQLFiddle

【讨论】:

  • 这很好用,但看起来它正在为每个项目返回第一个(最早的)note。我试图让note 始终是最新的。
  • 已更新。您只需将 i1 更改为 i2
【解决方案2】:

您可以同时计算 first 和 last 并在连接条件中使用它们,如下所示:

SELECT i.item, i.note, i.record_date AS created, i.user AS created_by
FROM item i
INNER JOIN (
    SELECT item
        , MAX(record_date) as lastDate
        , MIN(record_date) as firstDate
    FROM item
    GROUP BY item
) AS flDates
ON i.item = flDates.item 
   AND i.record_date IN (flDates.firstDate, flDates.lastDate)

或者,您可以通过在子查询上使用 UNION 来获得更快的查询,并避免上述 IN 条件所暗示的索引浪费 OR,如下所示:

SELECT i.item, i.note, i.record_date AS created, i.user AS created_by
FROM item i
INNER JOIN (
    SELECT item, MIN(record_date) as record_date
    FROM item
    GROUP BY item
    UNION
    SELECT item, MAX(record_date) as record_date
    FROM item
    GROUP BY item
) AS flDates
ON i.item = flDates.item AND i.record_date = flDates.record_date

如果表在(item, record_date)上有索引,则更有可能比第一个版本更快;但如果没有这样的索引,MINMAX 值的单独计算最终可能会花费更长的时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    • 1970-01-01
    • 2018-10-13
    相关资源
    最近更新 更多