2010-04-29 5 views
1

У меня есть таблица с двумя столбцами, идентификатор клиента и порядок. Скажем, у меня есть в общей сложности идентификаторов заказов 1,2,3,4Заполните пропущенные значения в инструкции SELECT

Все клиент может иметь все четыре заказа, как показано ниже:

1234 1 
    1234 2 
    1234 3 
    1234 4 
    3245 3 
    3245 4 
    5436 2 
    5436 4 

Вы можете видеть выше, что 3245 клиент не имеют порядок идентификатор 1 или 2. Как я могу печатать в выходных данных запроса, как:

3245 1 
3245 2 
5436 1 
5436 3 

EDIT: Я не имею таблицу заказа, но у меня есть список того, как мы можем жестко закодировать его в запросе (1,2,3,4).

+0

Так что вы на самом деле ищете являются Пробелами (т.е. те, которые не имеют заданные номер заказа). У вас есть главный список номеров заказов, которые все клиенты ДОЛЖНЫ иметь? Хотя это звучит не так. Потому что, если у вас есть один клиент, приходите за один раз, но другой приходит в 100 раз, вы не хотите, чтобы у каждого было более 100 заказов. – DRapp

+0

Вы хотите узнать клиентов, которые не связаны с этими заказами? –

+0

здесь. Один клиент с max может иметь только 4 заказа, и один заказ не выполняется дважды одним клиентом. – Vijay

ответ

3
SELECT c.id, o.order 
FROM (
     SELECT 1 AS order 
     UNION ALL 
     SELECT 2 AS order 
     UNION ALL 
     SELECT 3 AS order 
     UNION ALL 
     SELECT 4 AS order 
     ) o 
CROSS JOIN 
     (
     SELECT DISTINCT id 
     FROM customer_orders 
     ) c 
WHERE NOT EXISTS 
     ( 
     SELECT NULL 
     FROM customer_orders ci 
     WHERE ci.id = c.id 
       AND ci.order = o.order 
     ) 

Если у вас есть customers стол, он становится более простым:

SELECT c.id, o.order 
FROM (
     SELECT 1 AS order 
     UNION ALL 
     SELECT 2 AS order 
     UNION ALL 
     SELECT 3 AS order 
     UNION ALL 
     SELECT 4 AS order 
     ) o 
CROSS JOIN 
     customers c 
WHERE NOT EXISTS 
     ( 
     SELECT NULL 
     FROM customer_orders ci 
     WHERE ci.id = c.id 
       AND ci.order = o.order 
     ) 
+0

Отлично. Это именно то, что мне нужно.BYW Я получаю ожидаемый результат, но вы могли бы рассказать о части WHERE? – Vijay

+0

@benjamin: запрос создает все возможные комбинации клиентов/заказов с помощью 'CROSS JOIN', а затем фильтрует их с помощью' NOT EXISTS', возвращая только те, которые не имеют соответствия в 'customer_orders'. – Quassnoi

0

в стороне от моего комментария, и существующая таблица, я бы подойти что-то вроде этого ...

select distinct 
     a.Customer, 
     b.OrderNumber 
    from 
     YourOrderTable a, 
     (select distinct OrderNumber from YourOrderTable) b 
    where 
     b.OrderNumber NOT IN 
      (select OrderNumber from 
       YourOrderTable c 
       where a.Customer = c.Customer 
        and b.OrderNumber = c.OrderNumber) 

Выполняя выделение, отличное как вторая таблица в предложении FROM, и никакое конкретное соединение с ним, вы получите декартовое соединение ... то есть: для каждого клиента он будет присоединяться ко всем возможным или der number.

Тогда в предложении WHERE тест NOT IN SQL разрешит только «b». порядковые номера, где ни один не существуют в SQL-подвыборки (с.)

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

+0

У меня всего 4 заказа. Так что это не было бы дорогостоящим – Vijay

1

Хорошо, есть две проблемы. Первой проблемой является преобразование списка чисел в набор строк. Существует несколько различных способов сделать это, в зависимости от того, как вы получаете числа в запросе. В следующем примере я использую функцию, которая превращает строку, разделенную запятыми, в вложенную таблицу, которую можно рассматривать как обычную таблицу с помощью функции TABLE(). Это не относится к вопросу, который вы ставите. Если вас интересует этот бит реализации, см. my post in this other thread.

Вторая часть проблемы - идентификация недостающих заказов для каждого Клиента. Очевидные подходы - например, использование NOT IN с подзапросом - не будут работать, потому что Orders для Customer 1234 соответствуют всем идентификаторам заказа. Нам нужно заполнить недостающие заказы для каждого Клиента. Это можно сделать, используя LEFT OUTER JOIN в сочетании с предложением PARTITION BY. Именно тогда простой вопрос, чтобы отфильтровать хиты путем внедрения запроса Лей во внешнем SELECT, как это:

SQL> select customer_id 
    2   , missing_order_id 
    3 from (
    4  select t42.customer_id 
    5    , t42.order_id 
    6    , nos.column_value as missing_order_id 
    7  from (select * from table (str_to_number_tokens('1,2,3,4'))) nos 
    8  left outer join t42 partition by (t42.customer_id) 
    9  on nos.column_value = t42.order_id 
10  ) 
11 where order_id is null 
12/

CUSTOMER_ID MISSING_ORDER_ID 
----------- ---------------- 
     3245    1 
     3245    2 
     5436    1 
     5436    3 

SQL> 
Смежные вопросы