SQL - Как я могу вернуть идентификаторы из списка предложений where, которых нет в таблице? - PullRequest
2 голосов
/ 05 февраля 2011

Задан такой запрос:

select customerId
  from customer
 where customerId in (
          1, 2, 3
       )

У меня есть сотни идентификаторов в списке предложения where; как бы вернуть идентификаторы из списка в предложении where, которых нет в таблице?

Это рабочая таблица, к которой я могу только выполнить select запросов. Я могу только выполнить select запросов; У меня нет прав на создание таблиц.

Ответы [ 6 ]

6 голосов
/ 05 февраля 2011

Вы можете использовать оператор VALUES, чтобы подделать таблицу в вашем SELECT:

SELECT t1.customerId
FROM
  (VALUES (1), (2), (3), (4)) AS t1(customerId)
LEFT OUTER JOIN
  customer c
ON
  c.customerId = t1.customerId
AND
  c.customerId IS NULL

Ссылки

4 голосов
/ 05 февраля 2011

Существует гораздо более простой способ сделать это в DB2, используя VALUES для создания таблицы на лету:

select 
   customerID
from 
   table(values (1),(2),(3)) as a (customerID)  
except 
select 
   customerID 
from 
   customers;

Обратите внимание, что вам нужно поставить круглые скобки вокруг каждого значения, чтобы убедиться, что каждое значение"строка" в конструкции таблицы.

В этом примере, если ваша таблица customers имеет идентификаторы клиентов 1, 2, 3 и 4, этот запрос вернет значение 4.

Этодолжен работать на DB2 UDB для z / OS Версии 8 и новее.Он также будет работать на DB2 для Linux / UNIX / Windows.

3 голосов
/ 05 февраля 2011

Я бы поместил эти идентификаторы в структуру таблицы и оставил соединение с вашей таблицей клиентов.

select t.customerId
    from SomeTable t
        left join customer c
            on t.customerId = c.customerId
    where c.customerId is null
2 голосов
/ 05 февраля 2011

Действительно, очень жестокий подход , для большинства СУБД это будет работать (кроме Oracle, где вам нужно select..from dual). Это должно работать в DB2, даже если у вас нет доступа к созданию / обновлению таблиц и может только SELECT

select N1.N * 1000 + N2.N * 100 + N3.N * 10 + N4.N as NonExistentCustomerID
from (
    select 1 as N union all select 2 union all select 3 union all
    select 4 union all select 5 union all select 6 union all
    select 7 union all select 8 union all select 9 union all
    select 0) N1
cross join (
    select 1 as N union all select 2 union all select 3 union all
    select 4 union all select 5 union all select 6 union all
    select 7 union all select 8 union all select 9 union all
    select 0) N2
cross join (
    select 1 as N union all select 2 union all select 3 union all
    select 4 union all select 5 union all select 6 union all
    select 7 union all select 8 union all select 9 union all
    select 0) N3
cross join (
    select 1 as N union all select 2 union all select 3 union all
    select 4 union all select 5 union all select 6 union all
    select 7 union all select 8 union all select 9 union all
    select 0) N4
where N1.N * 1000 + N2.N * 100 + N3.N * 10 + N4.N in (1,2,3)
    and not exists (
        select * from customer c where c.customerid = v.number + v2.number*1000)

Разверните подзапросы, чтобы охватить весь диапазон номеров.

Если вы могли бы создать таблицы (или имел один удобный), вместо этого создайте таблицу «цифры» с цифрами от 0 до 9 (10 записей) и продолжайте присоединяться к себе, т.е.

create table Numbers (N int)
insert into Numbers
select 1 union all select 2 union all select 3 union all
select 4 union all select 5 union all select 6 union all
select 7 union all select 8 union all select 9 union all
select 0

select N1.N * 1000 + N2.N * 100 + N3.N * 10 + N4.N as NonExistentCustomerID
from numbers N1
cross join numbers N2
cross join numbers N3
cross join numbers N4
where N1.N * 1000 + N2.N * 100 + N3.N * 10 + N4.N in (1,2,3)
    and not exists (
        select * from customer c where c.customerid = v.number + v2.number*1000)

Таблица numbers всегда полезна для различных запросов.

Для справки для SQL Server , предполагая, что числа находятся в диапазоне 0-2047, вы можете использовать

select v.number
from master..spt_values v
left join customer c on c.customerid = v.number
where v.type='P' and v.number in (1,2,3)
  and v.customerid is null

Если вам нужен больший диапазон, продолжайте присоединяться к master..spt_values ​​снова, чтобы получить больший диапазон

select v.number + v2.number*1000 as NonExistentCustomerID
from master..spt_values v
inner join master..spt_values v2 on v2.type='P'
where v.type='P' and v.number + v2.number*1000 in (1,2,3)
  and v.number between 0 and 999
  and not exists (
    select * from customer c where c.customerid = v.number + v2.number*1000)
order by 1
1 голос
/ 05 февраля 2011

Один простой способ - использовать таблицу подсчета, скажем, она называется числами с номером столбца - всех чисел (этот код может быть не самым лучшим, но должно быть ясно, какова цель):

select number
from numbers
where number in (1, 2, 3)
and number NOT IN (select customerId from customer)

Другая возможность - записать искомые идентификаторы в реальную таблицу или табличную переменную.

1 голос
/ 05 февраля 2011
select customerId
  from customer
EXCEPT
select customerId
  from customer
 where customerId in (
          1, 2, 3
       )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...