2010-02-21 98 views
6

我遇到了問題(我想有一個小問題),我希望你能幫助我。 我使用Sybase SQL Anywhere和這裏是我的代碼:SQL選擇1列中的唯一值

SELECT TOP 4 Person.Id_person, Person.Name, Person.Surname, Visit.Date, Visit.Place 
From Person, Visit 
WHERE Visit.Id_person = Person.Id_person 
ORDER BY Visit.DATE DESC 

和這裏的結果:

3 | Paul | McDonald | 2010-01-19 | Ohio 
3 | Paul | McDonald | 2010-01-18 | New York 
19 | Ted | Malicky | 2009-12-24 | Tokyo 
12 | Meg | Newton | 2009-10-13 | Warsaw 

,我想不重複的保羅·麥克唐納,只有擁有第一(按日期)的訪問。我想有結果是這樣的:

3 | Paul | McDonald | 2010-01-19 | Ohio 
19 | Ted | Malicky | 2009-12-24 | Tokyo 
12 | Meg | Newton | 2009-10-13 | Warsaw 
.... 

我該怎麼辦?你可以幫幫我嗎? :(

+1

我不知道sybase *特別*,但是在很多數據庫中,您必須按天分組,然後重新展開,或者使用額外的WHERE條件來過濾掉其他預訂同一個人。 –

+0

@Alliah:對於訪問表,是(Id_Person,Date)唯一嗎? –

回答

1

您可以添加where not exists條款濾除前幾次訪問:

SELECT TOP 4 p1.Id_person, p1.Name, p1.Surname, v1.Date, v1.Place 
FROM Person p1, Visit v1 
WHERE p1.Id_person = v1.Id_person 
AND NOT EXISTS (
    SELECT * 
    From Person p2, Visit v2 
    WHERE v2.Id_person = p2.Id_person 
    AND p1.Id_person = p2.Id_person 
    AND v2.Date > v1.Date 
) 
ORDER BY v1.DATE DESC 

爲了提高可讀性,考慮重寫雙from作爲加盟例如,更改:

FROM Person v1, Visit v1 
WHERE v1.Id_person = p1.Id_person 

到:

FROM Person p1 
INNER JOIN Visit v1 ON v1.Id_person = p1.Id_person 
+0

非常感謝:) – Alliah

+0

@Alliah:請注意,此解決方案假定(Id_Person,Date)在訪問表上是唯一的。如果是這種情況,請使用此解決方案。如果沒有,這會產生重複。 –

+0

@Andomar:我在SQL Server中測試過它,因爲「Visit.Id_person = Person.Id_person」應該是「v1.Id_person = p1.Id_person」,所以失敗了。但是,也許它在Sybase中有效,我不知道。只要提到它,以防萬一。 –

4

這是一個不同的方式來做它usi納克ROW_NUMBER函數,以保證如果有人在同一天召開兩次會議它仍然有效:

SELECT TOP 4 
    Person.Id_person, 
    Person.Name, 
    Person.Surname, 
    T1.Date, 
    T1.Place 
FROM 
    (SELECT 
     *, 
     ROW_NUMBER() OVER (PARTITION BY Id_person ORDER BY Date DESC) AS rn 
    FROM Visit) AS T1 
JOIN Person 
ON T1.Id_person = Person.Id_person 
WHERE rn = 1 
ORDER BY Date DESC 

這裏的結果我得到:

Id_person Name Surname Date  Place 
3   Paul McDonald 2010-01-19 Ohio 
19  Ted Malicky 2009-12-24 Tokyo 
12  Meg Newton 2009-10-13 Warsaw 
1   Foo Bar  2009-06-03 Someplace 

這是我使用的測試數據:

CREATE TABLE Person (Id_person INT NOT NULL, Name NVARCHAR(100) NOT NULL, Surname NVARCHAR(100) NOT NULL); 
INSERT INTO Person (Id_person, Name, Surname) VALUES 
(3, 'Paul', 'McDonald'), 
(19, 'Ted', 'Malicky'), 
(12, 'Meg', 'Newton'), 
(1, 'Foo', 'Bar'), 
(2, 'Baz', 'Qux'); 

CREATE TABLE Visit (Id_person INT NOT NULL, Date DATE NOT NULL, Place NVARCHAR(100) NOT NULL); 
INSERT INTO Visit (Id_person, Date, Place) VALUES 
(3, '2010-01-19', 'Ohio'), 
(3, '2010-01-18', 'New York'), 
(19, '2009-12-24', 'Tokyo'), 
(12, '2009-10-13', 'Warsaw'), 
(1, '2009-06-03', 'Someplace'), 
(12, '2009-10-13', 'Anotherplace'), 
(2, '2009-05-04', 'Somewhere'); 

在SQL Server 2008上測試過,但我相信Sybase的語法是相似的。

+0

一個人可以同時在兩個地方? :) – Andomar

+1

@Andomar:不...相同的*日期*,不是同一時間。你不能同時在兩個地方,但理論上你可以在同一天進行兩次不同的訪問,甚至可能到不同的城市。 –

+0

如果您使用DateTime字段,那麼解決方案如果更簡單一些。 –

3

還有一個更簡單的方法,它會告訴你最近的每個人的行程,以及:

SELECT TOP 4 Person.Id_person, Person.Name, Person.Surname, Visit.Date, Visit.Place 
    From Person, Visit 
    WHERE Visit.Id_person = Person.Id_person 
     AND (Visit.[Date] = (Select Max([Date]) 
          From Visit Where (Person.Id_person=Visit.Id_Person))) 
    ORDER BY Visit.DATE DESC 

我在工作中使用的這種變體經常。唯一需要注意的是,訪問表中的「Date」字段是DateTime(當然,有人不能同時在兩個地方)。

+0

請注意,此解決方案還假定(Id_Person,Date)在Visit表上是唯一的。這可能是一個有效的假設,但OP沒有具體說明。我已經評論了這個問題,要求OP澄清這一點。 –

+0

@馬克拜爾斯 - 這就是爲什麼我在報告中提到有人不能同時在兩個地方。 –