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

时间:2018-08-06 14:41:16

标签: sql oracle group-by

我建立了一个查询(在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),因此我想从每个记录中取 first 记录“重复的”分组记录,并且仍然可以使用select *

我该怎么办?

(P.S。我尝试使用其他解决方案(使用over (partition ...)),但没有用,我需要弄清楚)

4 个答案:

答案 0 :(得分:1)

如果表(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
             );

答案 1 :(得分:1)

这是没有窗口功能

的另一种制作方法

您可以尝试在select中使用子查询,以使COUNT成为row_number并在子查询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 |

答案 2 :(得分:1)

如果您坚持在答案中使用此示例,则可以将当前查询合并到WITH块中,然后像下面这样选择DISTINCT:

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

如何

这是低效率的,尽管它适用于当前示例,但在实际的数据库中可能会变得凌乱。如果戈登的答案为您提供了理想的输出,那将是一个更好的解决方案。

答案 3 :(得分:0)

使用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子句中。