代码之家  ›  专栏  ›  技术社区  ›  OfirD

从每个嵌套的分组记录中选择第一个记录

  •  0
  • OfirD  · 技术社区  · 7 年前

    我构建了一个查询(在Oracle中),它从重复的行中选择最大日期为的任何行。我的问题是基于 here ,它使用嵌套分组:

    SELECT *
    FROM (
          SELECT Train, MAX(Time) as MaxTime
          FROM TrainTable
          GROUP BY Train
    ) r
    INNER JOIN TrainTable t
    ON t.Train = r.Train AND t.Time = r.MaxTime
    

    现在,因为该查询不考虑 Time (如评论所述 there ),我想把 第一 从每个“重复”分组记录中记录, 仍然可以使用 select * .

    我该怎么做?

    (P.S.我尝试使用另一种解决方案(使用 over (partition ...) ),但没用,我得想办法)

    4 回复  |  直到 7 年前
        1
  •  0
  •   Gordon Linoff    7 年前

    使用 row_number() :

    select t.*
    from (select t.*,
                 row_number() over (partition by train order by time desc) as seqnum
          from traintable t
         ) t
    where seqnum = 1;
    

    这将返回 任意的 当有匹配的领带时划船 time . SQL表表示 无序的 设置,因此没有“第一”行,除非另一列指定了该顺序。如果是,那么您可以在 order by 条款。

        2
  •  1
  •   Yogesh Sharma    7 年前

    如果你有 PK 在桌子上( TrainTable )那你就可以用 fetch first 从句 subquery :

    select t.*
    from traintable t
    where t.pk = (select t1.pk
                  from traintable t1
                  where t1.train = t.train 
                  order by t1.time desc
                  fetch first 1 rows only
                 );
    
        3
  •  1
  •   D-Shih    7 年前

    这是另一种不用 窗口函数

    您可以尝试在中使用子查询 select ,以获取 COUNT 为行数并设置 partition by 子查询中的列 where 条款。

    CREATE TABLE TrainTable(
        train varchar(10),
        Time  date
    );
    INSERT INTO TrainTable values ('A',to_date('2017-01-01','YYYY-MM-DD'));
    INSERT INTO TrainTable values ('A',to_date('2018-01-01','YYYY-MM-DD'));
    INSERT INTO TrainTable values ('B',to_date('2017-05-01','YYYY-MM-DD'));
    INSERT INTO TrainTable values ('B',to_date('2017-05-05','YYYY-MM-DD'));
    INSERT INTO TrainTable values ('C',to_date('2017-01-01','YYYY-MM-DD'));
    

    问题1 :

    SELECT *
    FROM 
    (
        SELECT t.*,(SELECT 
                    COUNT(*) FROM TrainTable t1 
                    WHERE t1.Time >= t.Time AND 
                          t1.train = t.train
                   ) rn
        FROM TrainTable t
        ORDER BY t.Time DESC
    ) t
    where t.rn = 1
    

    Results :

    | TRAIN |                 TIME | RN |
    |-------|----------------------|----|
    |     A | 2018-01-01T00:00:00Z |  1 |
    |     B | 2017-05-05T00:00:00Z |  1 |
    |     C | 2017-01-01T00:00:00Z |  1 |
    
        4
  •  1
  •   Barry Piccinni    7 年前

    如果您坚持在回答中使用此示例,则可以将当前查询放入WITH块,然后选择DISTINCT like so:

    WITH query AS (
      SELECT r.*
      FROM (
        SELECT train, MAX(trainTime) as MaxTime
        FROM trainTimes
        GROUP BY train
      ) r
      INNER JOIN trainTimes t
      ON t.train = r.train AND t.trainTime = r.MaxTime
    )
    SELECT DISTINCT *
    FROM query;
    

    下面是一个SQL文件: SQL Fiddle

    然而

    这是低效的,虽然它适用于当前示例,但在实际的数据库中可能会变得混乱。如果Gordon的答案给了你想要的结果,那么这是一个更好的解决方案。