Sql 从每个嵌套的分组记录中选择第一个记录
我已经构建了一个查询(在Oracle中),从重复的行中选择任何具有最大日期的行。我的查询基于显示的查询,该查询使用嵌套分组:Sql 从每个嵌套的分组记录中选择第一个记录,sql,oracle,group-by,Sql,Oracle,Group By,我已经构建了一个查询(在Oracle中),从重复的行中选择任何具有最大日期的行。我的查询基于显示的查询,该查询使用嵌套分组: 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 现在,由于该查询不考虑Tim
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
(如注释所示)中的重复值,因此我希望从每个“重复”分组记录中取出第一个记录,并且仍然能够使用选择*
我怎么做
(另一方面,我尝试使用另一种解决方案(使用覆盖(分区…
),但它不起作用,我需要找出答案)使用行编号()
当存在匹配的时间的关联时,此操作将返回任意行。SQL表表示无序的集合,因此没有“第一”行,除非另一列指定该排序。如果是这样,那么您可以将该列包括在order by
子句中。使用行号()
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'));
当存在匹配的时间的关联时,此操作将返回任意行。SQL表表示无序的集合,因此没有“第一”行,除非另一列指定该排序。如果是这样,那么您可以将该列包括在order by
子句中。如果表(TrainTable
)中有PK
,那么您可以使用fetch first
子句和子查询
:
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
);
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'));
如果表(TrainTable
)中有PK
,则可以将fetchfirst
子句与子查询一起使用:
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
);
这里是另一种不用窗口功能的方法
您可以尝试在select
中使用子查询,以获取COUNT
be行号,并在子查询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
| TRAIN | TIME | RN |
|-------|----------------------|----|
| A | 2018-01-01T00:00:00Z | 1 |
| B | 2017-05-05T00:00:00Z | 1 |
| C | 2017-01-01T00:00:00Z | 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
| TRAIN | TIME | RN |
|-------|----------------------|----|
| A | 2018-01-01T00:00:00Z | 1 |
| B | 2017-05-05T00:00:00Z | 1 |
| C | 2017-01-01T00:00:00Z | 1 |
这里是另一种不用窗口功能的方法
您可以尝试在select
中使用子查询,以获取COUNT
be行号,并在子查询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
| TRAIN | TIME | RN |
|-------|----------------------|----|
| A | 2018-01-01T00:00:00Z | 1 |
| B | 2017-05-05T00:00:00Z | 1 |
| C | 2017-01-01T00:00:00Z | 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
| TRAIN | TIME | RN |
|-------|----------------------|----|
| A | 2018-01-01T00:00:00Z | 1 |
| B | 2017-05-05T00:00:00Z | 1 |
| C | 2017-01-01T00:00:00Z | 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版本:
但是
这是低效的,虽然它适用于当前示例,但在真实的DB中可能会变得混乱。如果Gordon的答案为您提供了所需的输出,那么这是一个更好的解决方案。如果您坚持在答案中使用此示例,您可以将当前查询合并到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版本:
但是
这是低效的,虽然它适用于当前示例,但在真实的DB中可能会变得混乱。如果Gordon的答案提供了所需的输出,那么这是一个更好的解决方案。那么基本上,您希望能够使用“SELECT*FROM”和Group By子句?老实说,即使您得到了满意的答案,它也不如学习和理解“其他解决方案”对分区的作用。理解起来更复杂,但很值得您花费时间。@Barrypicanni,我当然会这么做,但我也想知道如何使用这种查询:)所以基本上,您希望能够使用“SELECT*FROM”和Group By子句?老实说,即使您得到了满意的答案,它也不如学习和理解“其他解决方案”对分区的作用。理解起来更复杂,但也很值得你花时间。@Barrypicanni,我当然会这么做,但我也想知道如何使用这种查询:)如果不使用分区
,似乎没有足够简单和高效的方法来做,所以尽管这个答案没有使用原始查询,我会接受的。如果不使用分区
,似乎没有足够简单和高效的方法来完成它,所以尽管这个答案不使用原始查询,我还是会接受它。