2012-02-02 24 views
47

Tengo una lista de direcciones de correo electrónico, algunas de ellas están en mi mesa, algunas de ellas no. Quiero seleccionar todos los correos electrónicos de esa lista y si están en la tabla o no.T-SQL: cómo seleccionar valores en la lista de valores que NO ESTÁN EN LA tabla?

yo puede conseguir a los usuarios cuyas direcciones de correo electrónico se encuentran en la tabla como la siguiente:
SELECT u.* FROM USERS u WHERE u.EMAIL IN ('email1', 'email2', 'email3')

Pero, ¿cómo puedo seleccionar valores de esa lista que no se existe en la tabla?

Por otra parte, ¿cómo puedo seleccionar la siguiente manera:

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

Gracias de antemano.

+0

¿Se refiere a T-SQL de SQL Server de Microsoft? Si es así, ¿qué versión? – hvd

+1

Sí, servidor MS SQL. Estoy usando 2005 y 2008 R2 ambos. – kubilay

+0

Está bien, en ese caso, recomiendo la respuesta de Martin Smith. Lo pregunté porque incluso SQL Server 2000 todavía se usa una cantidad justa y su respuesta no funcionaría en eso. – hvd

Respuesta

65

Para 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) 

Para las versiones anteriores que puede hacer algo similar con una tabla derivada UNION ALL -ing las constantes.

/*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

¡gracias por brindar ambas soluciones! – user219628

+0

Hermoso. Gracias – dLight

6

Necesita crear de alguna manera una tabla con estos valores y luego usar NOT IN. Esto se puede hacer con una tabla temporal, un CTE (expresión de tabla común) o una Table Values Constructor (disponible en SQL-Server 2008):

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

El segundo resultado se puede encontrar con un LEFT JOIN o un sub consulta EXISTS:

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

Eso da los valores en la tabla que no están en la lista. La pregunta lo pregunta al revés: los de la lista que no están en la mesa. – hvd

+0

Con la edición, todavía no estará bien si 'Users.email' es anulable (y no sabemos si lo es) – hvd

+0

@hvd: Tiene razón, no sabemos si puede contener nulos. La consulta responderá correctamente sin embargo. –

2

Debe tener una tabla con la lista de mensajes de correo electrónico para verificar. A continuación, realice esta consulta:

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

Gracias, no quería ir con mucho camino. La respuesta de Martin lo hizo. – kubilay

1

Cuando no quieren tener los mensajes de correo electrónico en la lista que se encuentran en la base de datos que usted puede hacer lo siguiente:

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) 

esta manera obtendrá un resultado como

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

El uso de los operadores IN o EXISTS es más pesado que el de la izquierda en este caso.

Buena suerte :)

+0

Gracias, su respuesta es tardía pero correcta, también. Me alegro de no tener que crear una tabla de valores. – kubilay

+2

'EXISTS' será más eficiente que la unión externa, ya que puede provocar un cortocircuito. El suyo puede devolver la misma dirección varias veces si hay duplicados en 'Users'. Consulte [Subconsultas en expresiones CASE] (http://blogs.msdn.com/b/craigfr/archive/2006/08/23/715306.aspx) para obtener más detalles sobre cómo se maneja 'EXISTS'. –

0

Esto debería funcionar con todas las versiones de 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

Utilice esta: - SQL Server 2008 o posterior

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 
Cuestiones relacionadas