检索MySQL中每个record_id的每列的最后一条非空记录

时间:2016-08-31 02:01:53

标签: mysql sql

我有一个名为records的MySQL表。以下是其内容。

id  record_id   Data1   Data2   Time 
1   1           null    1       1/1/16
2   1           1       null    1/3/16
3   1           2       null    1/4/16
4   1           null    3       1/5/16
5   2           1       null    2/1/16
6   2           1       null    2/3/16
7   2           7       null    2/4/16
8   2           null    5       2/5/16

我想有一个MySQL查询来检索每个record_id的每列的最后一条非空记录。结果看起来像;

record_id   Data1   Data2   Time 
1           2       3       1/5/16
2           7       5       2/5/16

这个问题的棘手部分是涉及多个列。

4 个答案:

答案 0 :(得分:4)

SELECT t1.*
FROM yourTable t1
INNER JOIN
(
    SELECT record_id, MAX(Time) AS Time
    FROM yourTable
    GROUP BY record_id
) t2
    ON t1.record_id = t2.record_id AND
       t1.Time = t2.Time

如果您只想获得数据和时间列的最大值,请查看@Matt给出的答案。但是你的语言让人不清楚你真正想要的是什么。

<强>更新

这样的事情可能会给你想要的结果:

SELECT a.record_id,
       a.Data1,
       b.Data2,
       c.Time
FROM
(
    SELECT t1.record_id,
           t1.Data1
    FROM yourTable t1
    INNER JOIN
    (
        SELECT record_id,
               MAX(CASE WHEN Data1 IS NULL THEN 0 ELSE id END) AS Data1Id
        FROM yourTable
        GROUP BY record_id
    ) t2
        ON t1.record_id = t2.record_id AND
           t1.Id = t2.Data1Id
) a
INNER JOIN
(
    SELECT t1.record_id,
           t1.Data2
    FROM yourTable t1
    INNER JOIN
    (
        SELECT record_id,
               MAX(CASE WHEN Data2 IS NULL THEN 0 ELSE id END) AS Data2Id
        FROM yourTable
        GROUP BY record_id
    ) t2
        ON t1.record_id = t2.record_id AND
           t1.Id = t2.Data2Id
) b
    ON a.record_id = b.record_id
INNER JOIN
(
    SELECT t1.record_id,
           t1.Time
    FROM yourTable t1
    INNER JOIN
    (
        SELECT record_id,
               MAX(CASE WHEN Data2 IS NULL THEN 0 ELSE id END) AS TimeId
        FROM yourTable
        GROUP BY record_id
    ) t2
        ON t1.record_id = t2.record_id AND
           t1.Id = t2.TimeId
) c
    ON a.record_id = c.record_id

演示:

SQLFiddle

答案 1 :(得分:4)

这个可以解决你的问题:

select 
  record_id,
  substring_index(group_concat(Data1 order by Time desc), ',', 1) Data1,
  substring_index(group_concat(Data2 order by Time desc), ',', 1) Data2,
  substring_index(group_concat(Time  order by Time desc), ',', 1) Time
from records
group by record_id
;

它可能没有其他答案那么快,但是是另一个版本......试一试。如果表格中有Data3列,则可以复制/粘贴Data1列,只需将此列的所有引用更改为新列。

只是为了解释这是如何工作的:group_concat函数将列的所有非空值与分隔符(默认为,)连接起来。您可以在连接之前订购列。它有点像Oracle,Postgre和其他人的窗口函数...... substring_index只是得到第一个连接值,因为列表是按时间降序排列的。

答案 2 :(得分:1)

看起来你只想要最大的data1,max data2和max time,这将是简单的聚合:

SELECT
  record_id
  ,MAX(Data1) as Data1
  ,MAX(Data2) as Data2
  ,MAX(Time) as Time
FROM
  yourTable
GROUP BY
  record_id

SQL小提琴http://www.sqlfiddle.com/#!9/d95bc1/2

如果需要每列最新的非空值,您可以使用:

SELECT t.record_id, MAX(t.Data1) as Data1, MAX(t.Data2) as Data2, MAX(t.Time) as Time
FROM
  yourTable t
  LEFT JOIN
  (
    SELECT
      record_id, MAX(Time) as MaxTime
    FROM
      yourTable t
    WHERE
      Data1 IS NOT NULL
    GROUP BY
      record_id
  ) d1
  ON t.record_id = d1.record_id
  AND t.Time = d1.MaxTime
  LEFT JOIN
  (
    SELECT
      record_id, MAX(Time) as MaxTime
    FROM
      yourTable t
    WHERE
      Data2 IS NOT NULL
    GROUP BY
      record_id  
   ) d2
  ON t.record_id = d2.record_id
  AND t.Time = d2.MaxTime
WHERE
  d1.record_id IS NOT NULL
  OR d2.record_id IS NOT NULL
GROUP BY
  t.record_id

使用Tim的方法,您实际上仍然可以查看结果,查看最新的Data1记录,然后查看最新的Data2记录然后汇总,这样它们不仅仅是所有内容的MAX,而是代表Data1的最新2条记录1 1表示Data2。

这部分的SQL小提琴:http://www.sqlfiddle.com/#!9/d95bc1/10

答案 3 :(得分:1)

  

我希望有一个MySQL查询来检索每个record_id的每列的最后一条非空记录。

当然,还有一点不清楚的是你如何确定一行是 last 行,因为根据定义,数据库中的行是无序的。

因此,我的解释是,您希望每个不同Data1最后非空Data2Timerecord_id列值值。如果行值比另一行值高id,则行值被视为 last

假设我的理解是正确的,以下查询将起作用:

select t.record_id,
       (select t2.Data1 
          from tbl t2 
         where t2.record_id = t.record_id 
           and t2.Data1 is not null
          order by t2.id desc
          limit 1) as Data1,
       (select t2.Data2
          from tbl t2 
         where t2.record_id = t.record_id 
           and t2.Data2 is not null
          order by t2.id desc
          limit 1) as Data2,
       (select t2.Time
          from tbl t2 
         where t2.record_id = t.record_id 
           and t2.Time is not null
          order by t2.id desc
          limit 1) as Time
  from tbl t
group by t.record_id
order by t.record_id

SQLFiddle Demo