2013-04-03 98 views
0

我有日期的下表:甲骨文 - 在一個子集與最小值選擇行

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

我想要做的就是我想拉以最低的日期行(所有列,包括PK)(主要條件)和起始時間(次要條件)。例如,如果我們有

ROW1(日期= '2013年4月1日' 和開始時間= '14:00' )

ROW2(日期= '2013年4月2日'和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

你應該能夠做到這一點,如:

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

+0

答案是好的,但是當我查詢的其餘部分相結合是非常無效的。 – kyooryu

+0

@kyooryu也許如果你顯示了其餘的查詢?因爲你發佈的內容與我在結果中提供的答案相同。你可以改變小提琴的例子,把小提琴放在這裏供我們看。 – DazzaL

+0

我害怕我不能顯示比我已經發布的更多的查詢。我稍微擴展了這個問題,所以你可以看到我將會加入查詢的其餘部分。 – kyooryu

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 
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;