6 votes

Sélectionner les valeurs uniques dans une colonne SQL

J'ai un problème (un petit problème je suppose) et j'espère que vous m'aiderez. J'utilise Sybase Anywhere et voici mon code :

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

et voici le résultat :

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

et je ne voudrais pas dupliquer Paul McDonald, et avoir seulement la première visite (par la date). Je voudrais avoir un résultat comme ceci :

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

Que dois-je faire ? Pouvez-vous m'aider ? :(

4voto

Mark Byers Points 318575

Voici une façon différente de le faire en utilisant la fonction ROW_NUMBER pour garantir que si quelqu'un a deux réunions le même jour, cela fonctionne toujours :

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

Voici le résultat que j'obtiens :

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

Voici les données de test que j'ai utilisées :

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

Testé sur SQL Server 2008, mais je crois que la syntaxe pour Sybase est similaire.

3voto

Mark Brittingham Points 18970

Il existe un moyen plus simple et cela vous montrera également le voyage le plus récent pour chaque personne :

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

J'utilise une variante de cela assez souvent dans mon travail. La seule mise en garde est que le champ "Date" dans la table de visite est un DateTime (et, bien sûr, que quelqu'un ne peut pas être à deux endroits en même temps).

1voto

Andomar Points 115404

Vous pouvez ajouter une clause where not exists pour filtrer les visites antérieures:

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

Pour améliorer la lisibilité, envisagez de réécrire le double from comme une jointure. Par exemple, changez:

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

en:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X