Заполните пропущенные значения в операторе SELECT - PullRequest
1 голос
/ 29 апреля 2010

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

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

    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

РЕДАКТИРОВАТЬ: у меня нет таблицы заказов, но у меня есть список заказов, как мы можем жестко кодировать его в запросе (1,2,3,4).

Ответы [ 3 ]

3 голосов
/ 29 апреля 2010
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
        )
1 голос
/ 29 апреля 2010

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

Вторая часть проблемы - выявление недостающих заказов для каждого клиента. Очевидные подходы - такие как использование NOT IN с подзапросом - не будут работать, потому что Заказы для Клиента 1234 соответствуют всем идентификаторам Заказа. Нам нужно заполнить недостающие заказы для каждого клиента. Это можно сделать, используя LEFT OUTER JOIN в сочетании с предложением PARTITION BY. Тогда просто отфильтровать попадания, вставив запрос LOJ во внешний 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>
0 голосов
/ 29 апреля 2010

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

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, и без специального соединения с ней, вы получите декартово соединение ... т.е.

Затем в предложении WHERE тест NOT IN SQL разрешит только "b". порядковые номера там, где их нет в подвыборке SQL (c.)

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

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