2010-08-26 5 views
3

J'ai une table People (First_Name, Last_Name). Ce tableau a des documents qui sont dupliqués comme dans l'exemple (pas toutes les lignes sont dupliquées):SQL SELECT lignes distinctes à partir d'une table par plusieurs colonnes ignorant l'ordre des colonnes (importance)

First_Name Last_Name 
John  Smith 
Alec  Baldwin 
Smith  John 
Angelo  Gordon 
Mary  Bush 
Bush  Mary 

Comment puis-je sélectionner toutes les personnes distinctes? Dans la sortie finale de la requête, John Smith ne devrait apparaître qu'une seule fois (ce n'est pas important si dans la requête finale il y a John Smith ou Smith John).

Merci.

+0

Quelle version de SQL? – Tobiasopdenbrouw

+0

c'est MySQL 5.1. Je vous remercie. –

Répondre

5

Il suffit de choisir une commande et l'appliquer à travers tout le monde. Ensuite, utilisez une union qui permettra d'éliminer les doublons de toute façon

select FirstName,LastName from People where FirstName <= LastName 
union 
select LastName,FirstName from People where LastName < FirstName 
+0

Nice one. Souhaitez-vous utiliser cette version dans RL sur la réponse que j'ai posté? (Et pourquoi?) – Tobiasopdenbrouw

+0

C'est ça. Je vous remercie! –

+1

@Tobias - Eh bien, c'était la première réponse à laquelle je pensais, et je n'ai vu personne d'autre poster un message similaire. Je noterais que le vôtre dépend d'un caractère spécial ("") n'apparaissant pas dans ces colonnes, ce qui peut être ou ne pas être pertinent. En fonction de la taille de la table et de l'intelligence de l'optimiseur, cela peut conduire à deux scans de la table, mais je pense que les mêmes problèmes se posent à vous - cette sous-requête va scanner toute la table je pense. –

1

Désolé était missundertanding votre question sur le premier essai ...

WITH People (Firstname, Lastname) 
AS 
(
    SELECT 'John' AS Firstname, 'Smith' AS Lastname UNION 
    SELECT 'John' AS Firstname, 'Smith' AS Lastname UNION 
    SELECT 'Alec' AS Firstname, 'Baldwin' AS Lastname UNION 
    SELECT 'Smith' AS Firstname, 'John' AS Lastname UNION 
    SELECT 'John' AS Firstname, 'Smith' AS Lastname UNION 
    SELECT 'Angelo' AS Firstname, 'Gordon' AS Lastname UNION 
    SELECT 'Mary' AS Firstname, 'Bush' AS Lastname UNION 
    SELECT 'Bush' AS Firstname, 'Mary' AS Lastname 
) 
SELECT p1.* FROM People p1 
LEFT OUTER JOIN People p2 ON p2.Firstname = p1.Lastname AND p2.Lastname = p1.Firstname AND p2.Firstname < p1.Firstname 
WHERE p2.Firstname IS NULL 
+1

Ignorez-vous que 'Mary Bush' devrait être groupé avec 'Bush Mary'? – Tobiasopdenbrouw

+0

Oui, je pense qu'il est ... –

+0

Non les attributs first_name et last_name ont besoin de leur logique. Dans la réponse finale, il doit y avoir un enregistrement de John Smith pour les enregistrements initiaux de John Smith et de Smith John. –

3

C'est une façon de le faire en utilisant à peu près toute la saveur SQL.

DECLARE @Names TABLE (
    First_Name VARCHAR(32) 
    , Last_Name VARCHAR(32) 
) 

INSERT INTO @Names VALUES ('John', 'Smith') 
INSERT INTO @Names VALUES ('Alec', 'Baldwin') 
INSERT INTO @Names VALUES ('Smith', 'John') 
INSERT INTO @Names VALUES ('Angelo', 'Gordon') 
INSERT INTO @Names VALUES ('Mary', 'Bush') 
INSERT INTO @Names VALUES ('Bush', 'Mary') 

L'utilisation d'un JOIN

SELECT n1.* 
FROM @Names n1 
     LEFT OUTER JOIN @Names n2 ON n2.First_Name = n1.Last_Name 
            AND n2.Last_Name = n1.First_Name 
            AND n2.First_Name < n1.First_Name 
WHERE n2.First_Name IS NULL          

ou NOT EXISTS

SELECT n1.* 
FROM @Names n1 
WHERE NOT EXISTS (
      SELECT * 
      FROM @Names n2 
      WHERE n2.First_Name = n1.Last_Name 
        AND n2.Last_Name = n1.First_Name 
        AND n2.First_Name < n1.First_Name 
     ) 
0

Voici une solution qui utilise les fonctions d'Oracle. D'autres saveurs de SQL auront des fonctions identiques ou très similaires:

SQL> select * from t23 
    2/

FIRST_NAME      LAST_NAME 
------------------------------ ------------------------------ 
John       Smith 
Alec       Baldwin 
Smith       John 
Angelo       Gordon 
Mary       Bush 
Bush       Mary 

6 rows selected. 

SQL> select distinct least(first_name, last_name) 
    2     , greatest(first_name, last_name) 
    3 from t23 
    4/

LEAST(FIRST_NAME,LAST_NAME) GREATEST(FIRST_NAME,LAST_NAME) 
------------------------------ ------------------------------ 
Alec       Baldwin 
Bush       Mary 
John       Smith 
Angelo       Gordon 

SQL> 
0

Je pense que cela pourrait fonctionner dans MS-SQL

select * from gens

où (FirstName + "" + LastName) <> (+ LastName "" + FirstName)

0

Une autre sugestion

Tableau temporaire:

DECLARE @Names TABLE (
    First_Name VARCHAR(32) 
    , Last_Name VARCHAR(32) 
) 

INSERT INTO @Names VALUES ('John', 'Smith') 
INSERT INTO @Names VALUES ('Alec', 'Baldwin') 
INSERT INTO @Names VALUES ('Smith', 'John') 
INSERT INTO @Names VALUES ('Angelo', 'Gordon') 
INSERT INTO @Names VALUES ('Mary', 'Bush') 
INSERT INTO @Names VALUES ('Bush', 'Mary') 

En utilisant CASE

SELECT DISTINCT 
    CASE WHEN First_Name <= Last_Name THEN First_Name ELSE Last_Name END AS First_Name, 
    CASE WHEN First_Name <= Last_Name THEN Last_Name ELSE First_Name END AS Last_Name 
FROM @Names 
Questions connexes