2010-02-21 3 views
6

У меня проблема (небольшая проблема, я полагаю), и я надеюсь, вы мне поможете. Я использую Sybase 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 

Я использую вариант этого довольно часто в моей работе. Единственное предостережение в том, что поле «Дата» в таблице посещений является DateTime (и, конечно же, кто-то не может быть в двух местах одновременно).

+0

Обратите внимание, что это решение также предполагает (Id_Person, Date) уникально в таблице «Посещение». Это может быть допустимым предположением, но ОП не указал его. Я прокомментировал этот вопрос, попросив ОП разъяснить это. –

+0

@Mark Byers - вот почему я включил в свое предостережение, что кто-то не может быть в двух местах одновременно. –

Смежные вопросы