2012-09-05 29 views
1

特定列的最終值之間有一個與列的表中的記錄:獲取查詢要列出並在啓動和相同的ID

USE 'table'; 
insert into person values 
('11','xxx','1976-05-10','p1'), 
('11','xxx ','1976-06-11','p1'), 
('11','xxx ','1976-07-21','p2'), 
('11','xxx ','1976-08-31','p2'), 

任何人都可以建議我一個查詢以獲得關於他按時間順序改變的地點的人的開始和結束日期。

查詢我寫

SELECT PId,Name,min(Start_Date) as sdt, max(Start_Date) as edt, place 
from ** 
group by Place; 

只給了我答案的前兩行。任何人都可以提出查詢?

+1

你的問題是基於該順序非常的行,以及後面的兩行是否標識相同的地方。這些東西很難在SQL中表達出來,並且在應用程序級別上通常會更好地解決。 [小提琴可用](http://sqlfiddle.com/#!2/c1a86)爲那些誰想要嘗試不過。 – MvG

+0

如果你想匿名你的代碼,請不要破壞問題和答案。我已經把它回滾到了一個較早的完整版本。 –

+0

作爲警告,請勿再次擦除所有代碼。您可以在這裏匿名數據和名稱,但您需要保留核心問題。到目前爲止,您的編輯已使這個問題變得毫無意義,所以我不得不將它們推回兩次。 –

回答

1

這不是漂亮,而且性能可能是可怕的,但至少它works

select min(sdt), edt, place 
from (
    select A.Start_Date sdt, max(B.Start_Date) edt, A.place 
    from person A 
     inner join person B on A.place = B.place 
          and A.Start_Date <= B.Start_Date 
     left join person C on A.place != C.place 
         and A.Start_Date < C.Start_Date 
         and C.Start_Date < B.Start_Date 
    where C.place is null 
    group by A.Start_Date, A.place 
) X 
group by edt, place 

的想法是,AB代表所有雙行C將是這兩者之間具有不同place的任何行。因此,在C.place is null限制之後,我們知道AB屬於相同的範圍,即一組地方在一個地方,在它們之間按照時間順序沒有其他地方。從所有這些對中,我們想要識別那些具有最大範圍的那些,包含所有其他的那些。我們這樣做使用兩個嵌套的group by查詢。內部人員會爲每個可能的開始日期選擇最大結束日期,而外部人員會爲每個可能的結束日期選擇最小開始日期。結果是描述相同位置的按時間順序排列的最大範圍。

+0

OMG .. !!我無法相信這一點,它工作。我從來沒有想過,我可以得到答案。但一個非常委婉的解決方案。謝謝。 – user1635134

+0

上面的查詢只適用於1個ID「10 --- 01」,當添加這樣的ID時沒有工作。查詢中是否可以進行更改? – user1635134

+0

@ user1635134:您的原始查詢(現在從問題中缺失!)也不關心id,所以我保持簡單。要爲每個ID執行所有操作,必須在兩個連接的連接條件中包含id a),b)按兩個組的條件和c)作爲內部查詢結果中的附加列。 – MvG

0

這可以通過achived:

SELECT Id, PId, 
     MIN(Start_Date) AS sdt, 
     MAX(Start_Date) as edt, 
     IF(`place` <> @var_place_prev, (@var_rank:= @var_rank + 1), @var_rank) AS rank, 
     (@var_place_prev := `place`) AS `place` 
FROM person, (SELECT @var_rank := 0, @var_place_prev := "") dummy 
GROUP BY rank, Place; 

例子:SQLFiddle

如果你想記錄由ID責令則:

SELECT Id, PId, 
     MIN(Start_Date) AS sdt, 
     MAX(Start_Date) as edt, 
     `place` 
FROM(
    SELECT Id, PId, 
      Start_Date 
      IF(`place` <> @var_place_prev,(@var_rank:= @var_rank + 1),@var_rank) AS rank, 
      (@var_place_prev := `place`) AS `place` 
    FROM person, (SELECT @var_rank := 0, @var_place_prev := "") dummy 
    ORDER BY ID ASC 
    ) a 
GROUP BY rank, Place; 
+0

感謝您的簡要說明。 – user1635134

+1

您的解決方案非常依賴於MySQL遍歷表的順序。如果該訂單[更改](http://sqlfiddle.com/#!2/aea44/1),結果不正確。由於MySQL不對其處理關係的順序做出任何保證,因此在對數據或數據庫服務器升級進行一些更改後,您的查詢可能會在現在或將來某個時間點產生不正確的結果。 – MvG

+0

雅正確!第二個查詢保證記錄的順序。我故意發佈第一個查詢,因爲它比第二個更好。 – Omesh