Oracle - 选择子集中具有最小值的行

时间:2013-04-03 15:10:25

标签: sql oracle oracle10g

我有一张下列日期表:

dateID INT (PK),
personID INT (FK),
date DATE,
starttime VARCHAR, --Always in a format of 'HH:MM'

我想要做的是我想为每个人提取最低日期(主要条件)和开始时间(次要条件)的行(所有列,包括PK)。例如,如果我们有

row1(date ='2013-04-01'和starttime = '14:00')

row2(date ='2013-04-02'和starttime = '08:00')

将检索row1以及所有其他列。

到目前为止,我已经提出了逐步过滤表格,但它非常混乱。有更有效的方法吗?

这是我到目前为止所做的:

    SELECT 
    D.id
    , D.personid
    , D.date        
    , D.starttime 
FROM table D 
JOIN (
        SELECT --Select lowest time from the subset of lowest dates
            A.personid, 
            B.startdate, 
            MIN(A.starttime) AS starttime 
        FROM table A 
        JOIN (
                SELECT --Select lowest date for every person to exclude them from outer table
                    personid
                    , MIN(date) AS startdate
                FROM table
                GROUP BY personid
            ) B
        ON A.personid = B.peronid
        AND A.date = B.startdate
        GROUP BY 
            A.personid, 
            B.startdate
    ) C
ON C.personid = D.personid
AND C.startdate = D.date 
AND C.starttime = D.starttime

它有效,但我认为有一种更干净/有效的方法。有什么想法吗?

编辑:让我扩展一个问题 - 我还需要为每个人提取最长日期(只有日期,没有时间)。

结果应如下所示:

id
personid
max(date) for each person
min(date) for each person
min(starttime) for min(date) for each person

它是一个更大的查询的一部分(结果表与它连接),结果表必须足够轻量级,以便查询不会执行太长时间。使用此表的单个连接(仅对我想要的每个字段使用min,max),查询花了大约3秒钟,我希望生成的查询不会超过2-3倍。

3 个答案:

答案 0 :(得分:3)

你应该能够这样做:

select a.dateID, a.personID, a.date, a.max_date, a.starttime
  from (select t.*, 
               max(t.date) over (partition by t.personID) max_date,
               row_number() over (partition by t.personID 
                                  order by t.date, t.starttime) rn
          from table t) a
 where a.rn = 1;

示例数据添加到小提琴:http://sqlfiddle.com/#!4/63c45/1

答案 1 :(得分:0)

这是您可以使用的查询,无需在查询中加入。您也可以将@ Dazzal的查询作为独立使用

SELECT ID, PERSONID, DATE, STARTTIME
(
SELECT ID, PERONID, DATE, STARTTIME, ROW_NUMBER() OVER(PARTITION BY personid ORDER BY     STARTTIME, DATE) AS RN
FROM TABLE 
) A
WHERE 
RN = 1

答案 2 :(得分:0)

select a.id,a.accomp, a.accomp_name, a.start_year,a.end_year, a.company
  from (select t.*, 
               min(t.start_year) over (partition by t.company) min_date,
               max(t.end_year) over (partition by t.company) max_date,
               row_number() over (partition by t.company 
                                  order by t.end_year desc) rn
          from temp_123 t) a
 where a.rn = 1;