Sql 在Oracle中,如何为给定列中的每个不同值返回1行?
我有数据看起来像Sql 在Oracle中,如何为给定列中的每个不同值返回1行?,sql,oracle,greatest-n-per-group,sql-limit,Sql,Oracle,Greatest N Per Group,Sql Limit,我有数据看起来像 NBR ID DT 1 1 01-DEC-01 1 2 01-JAN-01 2 3 01-JAN-01 2 4 O2-JAN-01 我只想为每个NBR获取一行,其中包含最早的日期。 所以我希望结果是 NBR ID DT 1 2 01-JAN-01 2 3 01-JAN-01 但是,我不能使用LIMIT,因为我使用的是Oracle。我尝试了以下方法,但没有达到我预期的效果 select DISTINCT N
NBR ID DT
1 1 01-DEC-01
1 2 01-JAN-01
2 3 01-JAN-01
2 4 O2-JAN-01
我只想为每个NBR
获取一行,其中包含最早的日期。
所以我希望结果是
NBR ID DT
1 2 01-JAN-01
2 3 01-JAN-01
但是,我不能使用LIMIT
,因为我使用的是Oracle。我尝试了以下方法,但没有达到我预期的效果
select DISTINCT NBR, ID, DT
from tablename
group by NBR, ID, DT
order by DT
编辑:这不是该链接的副本,因为我是按NBR分组的。我希望每个不同的NBR对应一行。解决方案与
限制
或按
订购、Oracle与否无关。您希望使用行数
分析函数轻松解决此问题:
select nbr, id, dt
from (select nbr, id, dt,
row_number() over (partition by nbr order by dt) as rn
from tbl)
where rn = 1
我和这个网站上的其他人一样喜欢窗口功能和CTE。这是一个老派的方式,不使用这些乐趣。注意:如果NBR有重复的DT
,您将得到该NBR
如果有重复的最早DT
perNBR
,您可以进行另一个级别的聚合,因此这变得更加疯狂。在下一级,您将获得min(ID)
,然后将其与表关联。如果窗口功能是一个选项,那么它们确实是一个更好的选择
SELECT t1.*
FROM
tablename t1
INNER JOIN
(
SELECT t.NBR, MIN(t.ID) AS ID
FROM
tablename t2
INNER JOIN
(
SELECT
NBR
,MIN(DT) AS DT
FROM
tablename t3
GROUP BY
NBR
) g
ON t.NBR = g.NBR
AND t.DT = g.DT
GROUP BY
t.NBR
) m
ON t1.NBR = m.NBR
AND t1.ID = m.ID
您还可以使用:
您可以与聚合函数一起使用:
Oracle安装程序:
CREATE TABLE table_name ( NBR, ID, DT ) AS
SELECT 1, 1, DATE '2001-12-01' FROM DUAL UNION ALL
SELECT 1, 2, DATE '2001-01-01' FROM DUAL UNION ALL
SELECT 2, 3, DATE '2001-01-01' FROM DUAL UNION ALL
SELECT 2, 4, DATE '2001-01-02' FROM DUAL;
SELECT NBR,
MAX( ID ) KEEP ( DENSE_RANK FIRST ORDER BY DT ) AS ID,
MIN( DT ) AS DT
FROM table_name
GROUP BY NBR;
NBR ID DT
---------- ---------- -------------------
1 2 2001-01-01 00:00:00
2 3 2001-01-01 00:00:00
查询:
CREATE TABLE table_name ( NBR, ID, DT ) AS
SELECT 1, 1, DATE '2001-12-01' FROM DUAL UNION ALL
SELECT 1, 2, DATE '2001-01-01' FROM DUAL UNION ALL
SELECT 2, 3, DATE '2001-01-01' FROM DUAL UNION ALL
SELECT 2, 4, DATE '2001-01-02' FROM DUAL;
SELECT NBR,
MAX( ID ) KEEP ( DENSE_RANK FIRST ORDER BY DT ) AS ID,
MIN( DT ) AS DT
FROM table_name
GROUP BY NBR;
NBR ID DT
---------- ---------- -------------------
1 2 2001-01-01 00:00:00
2 3 2001-01-01 00:00:00
输出:
CREATE TABLE table_name ( NBR, ID, DT ) AS
SELECT 1, 1, DATE '2001-12-01' FROM DUAL UNION ALL
SELECT 1, 2, DATE '2001-01-01' FROM DUAL UNION ALL
SELECT 2, 3, DATE '2001-01-01' FROM DUAL UNION ALL
SELECT 2, 4, DATE '2001-01-02' FROM DUAL;
SELECT NBR,
MAX( ID ) KEEP ( DENSE_RANK FIRST ORDER BY DT ) AS ID,
MIN( DT ) AS DT
FROM table_name
GROUP BY NBR;
NBR ID DT
---------- ---------- -------------------
1 2 2001-01-01 00:00:00
2 3 2001-01-01 00:00:00
它是双重的!:)应该是他搜索的内容。这不是该链接的副本,因为我是按NBR分组的。我想为每个不同的NBR返回一行。但我只想在NBR有重复的早期DT时返回一行。行数窗口函数是最好的,因为这不是一个选项。如果它们是重复的最低id,您将如何选择哪个记录?@user6347191如果您真的不想通过窗口函数执行此操作,请查看我的答案底部,当存在重复的最早DT时,根据NBR
DT=MIN(DT)
is invalid SQL,您将可以任意获得1条记录。另外:Oracle实际上是第一个支持窗口功能的DBMS。它已经有了它的版本8@a_horse_with_no_name谢谢你给我的提示,我基本上从来没有写过oracle语法,我把min(id)改为id,min(dt)改为dt。我只是写了一个疯狂的答案,因为用户似乎对窗口功能有反感,但我很高兴知道oracle是第一个支持的!