2011-03-01 123 views
3

首先我會告訴你我的問題所屬的示例表,然後我會問這個問題。混淆SELECT語句

[my_fruits] 
fruit_name | fruit_id | fruit_owner | fruit_timestamp 
---------------------------------------------------------------- 
Banana  | 3   | Timmy  | 3/4/11 
Banana  | 3   | Timmy  | 4/1/11 
Banana  | 8   | Timmy  | 5/2/11 
Apple  | 4   | Timmy  | 2/1/11 
Apple  | 4   | Roger  | 3/4/11 

現在我想運行一個查詢,只選擇fruit_name,fruit_id和fruit_owner值。我只想得到每個水果一行,我想要它決定的方式是最新的時間戳。例如在此表上完美的查詢將返回:

[my_fruits] 
fruit_name | fruit_id | fruit_owner | 
---------------------------------------------- 
Banana  | 8   | Timmy  | 
Apple  | 4   | Roger  | 

我試着查詢:

select max(my_fruits.fruit_name) keep 
    (dense_rank last order by my_fruits.fruit_timestamp) fruit_name, 
     my_fruits.fruit_id, my_fruits.fruit_owner 
from my_fruits 
group by my_fruits.fruit_id, my_fruits.fruit_owner 

現在有了這個問題是回報基本上不同的水果名稱,水果ID和水果的業主。

回答

3

對於Oracle 9i +,用途:

SELECT x.fruit_name, 
     x.fruit_id, 
     x.fruit_owner 
    FROM MY_FRUIT x 
    JOIN (SELECT t.fruit_name, 
       MAX(t.fruit_timestamp) AS max_ts 
      FROM MY_FRUIT t 
     GROUP BY t.fruit_name) y ON y.fruit_name = x.fruit_name 
           AND y.max_ts = x.fruit_timestamp 

SELECT x.fruit_name, 
     x.fruit_id, 
     x.fruit_owner 
    FROM (SELECT mf.fruit_name, 
       mf.fruit_id, 
       mf.fruit_owner, 
       ROW_NUMBER() OVER (PARTITION BY mf.fruit_name 
             ORDER BY mf.fruit_timestamp) AS rank 
      FROM MY_FRUIT mf) x 
WHERE x.rank = 1 

大多數數據庫將支持使用自上派生表/內嵌視圖加盟

但是,如果有+2個fruit_name記錄具有相同的時間戳值,則這將返回重複項。

1

嘗試一個子查詢:

select a.fruit_name, a.fruit_id, a.fruit_owner 
from my_fruits a 
where a.fruit_timestamp = 
(select max(b.fruit_timestamp) 
    from my_fruits b 
    where b.fruit_id = a.fruit_id) 
+1

這將返回重複,如果有2+ fruit_name記錄相同的時間戳值 – 2011-03-01 20:19:56

+0

是的,但它會正確地返回2條記錄,如果2個不同fruit_owners有最新fruit_timestamp。 – 2011-03-01 20:51:50

+0

這也不是什麼OP希望 – 2011-03-01 21:50:04

0

我會通過找出您感興趣的(fruit_name,fruit_timestamp)列表,然後將該「表」與實際水果表分組並檢索其他值來完成此操作。

SELECT fruit_and_max_t.fruit_name, 
     my_fruits.fruit_id, 
     my_fruits.fruit_owner 
FROM my_fruits, 
    (SELECT fruit_name, MAX(fruit_timestamp) AS max_timestamp 
    FROM my_fruits 
    GROUP BY fruit_name) AS fruit_and_max_t, 
WHERE fruit_and_max_t.max_timestamp = my_fruits.fruit_timestamp 
    AND fruit_and_max_t.fruit_name = my_fruits.fruit_name 

這假定有沒有在表中的多個條目與(fruit_name,fruit_timestamp)相同的值,即像的唯一標識符的元組(一對)的行爲。

+0

我會投票支持ANSI-92語法,這是不是 - 這是ANSI-89。但隨後它會是相同的東西我已經張貼在我的答案... – 2011-03-01 20:24:45

+0

@OMG小馬 - 真有關語法,和真實的,我沒有看到你的答案張貼我自己的時候。我個人發現舊的語法更容易理解,但也許這只是因爲我習慣了! – 2011-03-01 20:27:55

+0

ANSI-89語法不是一個好習慣,沒有外部連接支持。 – 2011-03-01 20:29:04

2

如果你想每個水果名稱有一行,你必須按fruit_name分組。

select fruit_name, 
     max(my_fruits.fruit_id) keep 
      (dense_rank last order by my_fruits.fruit_timestamp) fruit_id, 
     max(my_fruits.fruit_owner) keep 
      (dense_rank last order by my_fruits.fruit_timestamp) fruit_owner 
from my_fruits 
group by my_fruits.fruit_name 

如何處理tie-breaks是一個單獨的問題。