2010-02-21 42 views
6

Tengo un problema (un pequeño problema, supongo) y espero que me ayudes. Puedo utilizar Sybase en cualquier lugar y aquí está mi código:SQL Seleccionar valores únicos en 1 columna

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 

y aquí está el resultado:

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 

y me gustaría no duplicar Paul McDonald, y sólo tienen en primer lugar (por la fecha) visita. Me gustaría tener un resultado como este:

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

¿Qué debo hacer? ¿Usted me podría ayudar? :(

+1

No sé sybase * específicamente *, pero en muchas bases de datos tendría que agrupar por día tomando el mínimo y luego volver a expandir, o usar una condición adicional 'WHERE' para filtrar las reservas adicionales para el misma persona. –

+0

@Alliah: para la tabla de visitas, ¿es (Id_Person, Date) único? –

Respuesta

1

Usted puede agregar una cláusula where not exists para filtrar las visitas anteriores:

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 

para mejorar la legibilidad, considere volver a escribir el doble from como un join Por ejemplo, cambie:.

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 
+0

muchas gracias :) – Alliah

+0

@Alliah: Tenga en cuenta que esta solución asume que (Id_Person, Fecha) es único en la tabla de visitas. Si ese es el caso, use esta solución. Si no, esto producirá duplicados. –

+0

@Andomar: Probé esto en SQL Server y falló porque "Visit.Id_person = Person.Id_person" debería ser "v1.Id_person = p1.Id_person". Pero tal vez funciona en Sybase, no lo sé. Solo mencionarlo en caso de que ayude. –

4

Aquí hay una manera diferente de hacerlo usi ng de la función ROW_NUMBER para asegurar que si alguien tiene dos reuniones en el mismo día todavía funciona:

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 

Aquí está el resultado me sale:

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 

He aquí los datos de prueba utilicé:

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

Probado en SQL Server 2008, pero creo que la sintaxis de Sybase es similar.

+0

Una persona puede estar en dos lugares al mismo tiempo? :) – Andomar

+1

@Andomar: No ... la misma * fecha *, no a la misma hora. No puede estar en dos lugares al mismo tiempo, pero teóricamente podría hacer dos visitas diferentes el mismo día, posiblemente incluso en diferentes ciudades. –

+0

Si usa un campo DateTime, entonces la solución es bastante simple. –

3

hay una manera más fácil y te mostraré el viaje más reciente para cada persona, así:

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 

utilizo una variante de esto muy a menudo en mi trabajo. La única advertencia es que el campo "Fecha" en la tabla de visitas es un DateTime (y, por supuesto, que alguien no puede estar en dos lugares al mismo tiempo).

+0

Tenga en cuenta que esta solución también asume (Id_Person, Date) es única en la tabla de visitas. Esta podría ser una suposición válida, pero el OP no la especificó. He comentado sobre la pregunta, pidiendo al OP que aclare esto. –

+0

@Mark Byers: por eso incluí en mi advertencia que alguien no puede estar en dos lugares al mismo tiempo. –

Cuestiones relacionadas