2012-02-02 21 views
47

Ho una lista di indirizzi e-mail, alcuni dei quali sono nella mia tabella, altri no. Voglio selezionare tutte le e-mail da quella lista e se sono nella tabella o no.T-SQL: come selezionare i valori nella lista valori che NON sono nella tabella?

posso ottenere gli utenti i cui indirizzi di posta sono nella tabella come questa:
SELECT u.* FROM USERS u WHERE u.EMAIL IN ('email1', 'email2', 'email3')

Ma come faccio a selezionare i valori in quella lista che non sono esiste nella tabella?

Inoltre, come posso selezionare in questo modo:

E-Mail | Status 
email1 | Exist 
email2 | Exist 
email3 | Not Exist 
email4 | Exist 

Grazie in anticipo.

+0

Vuoi dire T-SQL da Microsoft SQL Server? Se sì, quale versione? – hvd

+1

Sì, MS SQL Server. Sto usando sia il 2005 che il 2008 R2. – kubilay

+0

Ok, in tal caso raccomando la risposta di Martin Smith. Ho chiesto perché anche SQL Server 2000 è ancora utilizzato in modo equo e la sua risposta non funzionerebbe su questo. – hvd

risposta

65

Per SQL Server 2008

SELECT email, 
     CASE 
     WHEN EXISTS(SELECT * 
        FROM Users U 
        WHERE E.email = U.email) THEN 'Exist' 
     ELSE 'Not Exist' 
     END AS [Status] 
FROM (VALUES('email1'), 
       ('email2'), 
       ('email3'), 
       ('email4')) E(email) 

Per le versioni precedenti si può fare qualcosa di simile con una tabella derivata UNION ALL -ing le costanti.

/*The SELECT list is the same as previously*/ 
FROM (
SELECT 'email1' UNION ALL 
SELECT 'email2' UNION ALL 
SELECT 'email3' UNION ALL 
SELECT 'email4' 
) E(email) 
+0

grazie per aver fornito entrambe le soluzioni! – user219628

+0

Bello. Grazie – dLight

6

È necessario in qualche modo creare una tabella con questi valori e quindi utilizzare NOT IN. Questo può essere fatto con una tabella temporanea, un CTE (espressione di tabella comune) o un Table Values Constructor (disponibile in SQL-Server 2008):

SELECT email 
FROM 
    (VALUES 
     ('email1') 
     , ('email2') 
     , ('email3') 
    ) AS Checking (email) 
WHERE email NOT IN 
     (SELECT email 
     FROM Users 
    ) 

Il secondo risultato può essere trovato con una LEFT JOIN o un EXISTS sottoquery:

SELECT email 
    , CASE WHEN EXISTS (SELECT * 
          FROM Users u 
          WHERE u.email = Checking.email 
         ) 
      THEN 'Exists' 
      ELSE 'Not exists' 
     END AS status 
FROM 
    (VALUES 
     ('email1') 
     , ('email2') 
     , ('email3') 
    ) AS Checking (email) 
+1

Questo dà i valori nella tabella che non sono nella lista. La domanda lo pone al contrario: quelli nella lista che non sono nella tabella. – hvd

+0

Con la modifica, non sarà ancora corretto se 'Users.email' è nullable (e non sappiamo se lo è) – hvd

+0

@hvd: hai ragione, non sappiamo se è nullable. La query risponderà correttamente però. –

2

Si dovrebbe avere una tabella con l'elenco delle e-mail da controllare. Poi fate questa domanda:

SELECT E.Email, CASE WHEN U.Email IS NULL THEN 'Not Exists' ELSE 'Exists' END Status 
FROM EmailsToCheck E 
LEFT JOIN (SELECT DISTINCT Email FROM Users) U 
ON E.Email = U.Email 
+0

Grazie, non volevo andare con la lunga strada. La risposta di Martin lo ha fatto. – kubilay

1

Quando non si vogliono avere le e-mail nella lista che si trovano nel database avrete possibile effettuare le seguenti operazioni:

select u.name 
     , u.EMAIL 
     , a.emailadres 
     , case when a.emailadres is null then 'Not exists' 
       else 'Exists' 
      end as 'Existence' 
from  users u 
      left join (   select 'email1' as emailadres 
        union all select 'email2' 
        union all select 'email3') a 
      on a.emailadres = u.EMAIL) 

questo modo si otterrà un risultato come

name | email | emailadres | existence 
-----|--------|------------|---------- 
NULL | NULL | [email protected] | Not exists 
Jan | [email protected] | [email protected]  | Exists 

Gli operatori IN o EXISTS sono più pesanti di quelli di sinistra in questo caso.

Buona fortuna :)

+0

Grazie, la tua risposta è in ritardo ma anche corretta. Sono contento di non dover creare una tabella per i valori. – kubilay

+2

'EXISTS' sarà più efficiente di outer join in quanto potrebbe causare cortocircuiti. Il vostro può riportare lo stesso indirizzo più volte se ci sono duplicati in 'Utenti'. Vedi [Subqueries in CASE Expressions] (http://blogs.msdn.com/b/craigfr/archive/2006/08/23/715306.aspx) per alcuni dettagli su come viene gestito 'EXISTS'. –

0

Questo dovrebbe funzionare con tutte le versioni SQL.

SELECT E.AccessCode , 
     CASE WHEN C.AccessCode IS NOT NULL THEN 'Exist' 
      ELSE 'Not Exist' 
     END AS [Status] 
FROM (SELECT '60552' AS AccessCode 
      UNION ALL 
      SELECT '80630' 
      UNION ALL 
      SELECT '1611' 
      UNION ALL 
      SELECT '0000' 
     ) AS E 
     LEFT OUTER JOIN dbo.Credentials C ON E.AccessCode = c.AccessCode 
0

Utilizzare questa: - SQL Server 2008 o versioni successive

SELECT U.* 
FROM USERS AS U 
Inner Join (
    SELECT 
    EMail, [Status] 
    FROM 
    (
     Values 
     ('email1', 'Exist'), 
     ('email2', 'Exist'), 
     ('email3', 'Not Exist'), 
     ('email4', 'Exist') 
    )AS TempTableName (EMail, [Status]) 
    Where TempTableName.EMail IN ('email1','email2','email3') 
) As TMP ON U.EMail = TMP.EMail 
Problemi correlati