在SELECT语句中填写缺失值

时间:2010-04-29 14:16:37

标签: sql mysql sql-server oracle

我有一个包含两列的表,客户ID和订单。 假设我的订单总数为1,2,3,4

所有客户都可以拥有所有四个订单,如下所示:

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

您可以在上面看到3245客户没有订单ID 1或2。 我怎么能在查询输出中打印如下:

3245 1
3245 2
5436 1
5436 3

编辑:我没有订单表,但我有一个订单列表,就像我们可以在查询中硬编码一样(1,2,3,4)。

3 个答案:

答案 0 :(得分: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
        )

答案 1 :(得分:1)

好的,这里有两个问题。第一个问题是将数字列表转换为行集。有许多不同的方法可以执行此操作,具体取决于您如何将数字输入查询。在下面的示例中,我使用一个函数将逗号分隔的字符串转换为嵌套表,可以将其视为具有TABLE()函数的常规表。这与您提出的问题并不严格相关。如果您对实施的这一部分感兴趣,请参阅my post in this other thread

问题的第二部分是确定每个客户的缺失订单。显而易见的方法 - 例如将NOT IN与子查询一起使用 - 将不起作用,因为客户订单1234匹配所有订单ID。我们需要做的是填写每个客户的缺失订单。这可以通过使用LEFT OUTER JOIN和PARTITION BY子句来完成。通过在外部SELECT中嵌入LOJ查询来过滤掉命中是一件简单的事情,如下所示:

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>

答案 2 :(得分: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 )

通过选择distinct作为FROM子句中的第二个表并且没有特定的连接,您将获得一个笛卡尔连接...即:对于每个客户,它将加入到每个可能的订单号。

然后,在WHERE子句中,NOT IN SQL测试将只允许“b”。 SQL-subselect(c。)

中不存在的订单号

这可能是一个非常昂贵的查询,特别是如果你有许多独特的订单..