T-SQL: ¿Cómo seleccionar Valores en la Lista de valores que NO ESTÁN EN la Tabla?


Tengo una lista de direcciones de correo electrónico, algunas de ellas están en mi tabla, otras no. Quiero seleccionar todos los correos electrónicos de esa lista y si están en la tabla o no.

Puedo obtener usuarios cuyas direcciones de correo están en la tabla de esta manera:
SELECT u.* FROM USERS u WHERE u.EMAIL IN ('email1', 'email2', 'email3')

Pero ¿cómo puedo seleccionar valores en esa lista que no existen en la tabla?

Además, ¿cómo puedo seleccionar así:

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

Gracias de antemano.

Author: Martin Smith, 2012-02-02

6 answers

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 versiones anteriores se 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)
 71
Author: Martin Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-02 13:41:42

Necesita crear de alguna manera una tabla con estos valores y luego usar NOT IN. Esto se puede hacer con una tabla temporal, una CTE (Expresión de tabla Común) o un Constructor de Valores de tabla (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 una subconsulta LEFT JOIN o 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)
 8
Author: ypercubeᵀᴹ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-02 13:46:03

Debe tener una tabla con la lista de correos electrónicos para verificar. Entonces haga 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
 2
Author: Lamak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-02 13:39:07

Cuando no quieras tener los correos electrónicos en la lista que están en la base de datos podrás 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)

De esta manera obtendrás 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 join izquierdo en este caso.

Buena suerte:)

 1
Author: Mark Kremers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-02 13:49:14

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
Author: Anju313,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-20 04:07:01

Use esto : -- 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
 0
Author: Ardalan Shahgholi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-29 22:50:44