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
per
NBR
,您可以进行另一个级别的聚合,因此这变得更加疯狂。在下一级,您将获得
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是第一个支持的!