如何为Oracle中给定列中的每个不同值返回1行?

时间:2016-06-16 20:22:16

标签: 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 NBR, ID, DT
from tablename
group by NBR, ID, DT
order by DT

编辑:这不是该链接的重复,因为我正在按照NBR进行分组。我希望每个不同的NBR都有一行。

4 个答案:

答案 0 :(得分:2)

该解决方案与limitorder by,Oracle无关。您希望使用row_number分析函数轻松解决此问题:

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

答案 1 :(得分:2)

您还可以使用the FIRST analytic function

select NBR,
  min(ID) keep (dense_rank first order by DT) as ID,
  min(DT) keep (dense_rank first order by DT) as DT
from tablename
group by NBR
order by DT;

       NBR         ID DT                
---------- ---------- -------------------
         2          3 2001-01-01 00:00:00
         1          2 2001-01-01 00:00:00

答案 2 :(得分:1)

您可以将KEEP ( DENSE_RANK FIRST ...)与聚合函数一起使用:

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 

答案 3 :(得分:0)

SELECT t.*
FROM
    tablename t
    INNER JOIN 
    (
       SELECT
          NBR
          ,MIN(DT) AS DT
       FROM
          tablename
       GROUP BY
          NBR
    ) g
    ON t.NBR = g.NBR
    AND t.DT = g.DT

我喜欢窗口功能和ctes,就像本网站上的其他人一样。这是一个老式的学校方式,不是为了好玩。请注意,如果NBR最早DT重复,您将获得NBR

的多行

如果每个DT最早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