【问题标题】:Transact SQL sub query事务 SQL 子查询
【发布时间】:2017-10-02 18:27:08
【问题描述】:

我想要一个查询,它将返回所有订单行项目都有库存的订单的 Order_ID 列表。以下是用于说明的表格:

test_Order:

Order_ID
1001
1002
1003

test_OrderLine:

OrderLine_ID|Order_ID|Item_ID|Quantity
10|1001|101|1
11|1001|102|1
12|1001|103|1
13|1002|101|4
14|1002|102|1
15|1003|101|1
16|1003|104|4

test_Item:

Item_ID|InStockQuantity
101|3
102|1
103|7

所以在上面的示例中,只应返回 Order_ID 1001,因为:

  • 在订单 1001 中,OrderLines 中的所有 3 个项目的数量都小于或等于 Items 中的 InStockQuantity。
  • 在订单 1002 中,项目 101 的数量为 4,但库存中只有 3 个。
  • 在订单 1003 中,商品表中不存在商品 104。

这显然是不正确的,但类似于:

SELECT O.Order_ID
FROM test_Order AS O
  LEFT JOIN test_OrderLine OL
    ON O.Order_ID = OL.Order_ID
  LEFT JOIN test_Item I
    ON OL.Item_ID = I.Item_ID
WHERE (OL.Quantity <= I.InStockQuantity)
GROUP BY O.Order_ID

该查询的问题是,只有一个 OrderLines 需要有一个 Quantity

我读过一些关于“ALL”运算符的文章,但看不出它在子查询中是如何工作的。

【问题讨论】:

  • 以 order_id 作为输入的存储过程如何创建一个临时表,在该表中迭代每个 item_id 并根据库存数量检查请求/订购的数量?

标签: sql-server subquery


【解决方案1】:

考虑此问题的另一种方法是返回没有需要数量大于库存数量的订单行的 order_id。使用左连接和coalesce 可以让您将完全缺货的商品视为数量为 0:

SELECT order_id
FROM   test_order
WHERE  order_id NOT IN (SELECT    order_id
                        FROM      test_orderline o
                        LEFT JOIN test_item i ON o.item_id = i.item_id 
                        WHERE     o.quantity > COALESCE(i.instockquantity, 0))

【讨论】:

  • 如果您在子查询中将and 更改为where,这将起作用。就像现在一样,它(子查询)将返回所有order_ids。
【解决方案2】:

使用not exists()

select o.Order_id
from test_Order as o
where not exists (
    select 1
    from test_OrderLine as ol
      left join test_Item as i
        on ol.Item_id = i.Item_id
    where ol.Order_id = o.Order_id
      and OL.Quantity > coalesce(I.InStockQuantity,0)
  )

rextester 演示:http://rextester.com/JGHQ62465

返回:

+----------+
| Order_id |
+----------+
|     1001 |
+----------+

【讨论】:

    【解决方案3】:

    这是一个小提琴:http://rextester.com/UPC62237

    我相信这会满足您的需求。我发表了评论,以便您了解查询背后的逻辑。

    create table test_Order ([Order_id] int); 
    insert into test_Order ([Order_id]) values 
     (1001)
    ,(1002)
    ,(1003);
    create table test_OrderLine ([OrderLine_id] int, [Order_id] int, [Item_id] int, [Quantity] int) ; 
    insert into test_OrderLine ([OrderLine_id], [Order_id], [Item_id], [Quantity]) values 
     (10, 1001, 101, 1) 
    ,(11, 1001, 102, 1)
    ,(12, 1001, 103, 1)
    ,(13, 1002, 101, 4)
    ,(14, 1002, 102, 1)
    ,(15, 1003, 101, 1)
    ,(16, 1003, 104, 4)
    ;
    create table test_Item ([Item_id] int, [InStockQuantity] int) ; 
    insert into test_Item ([Item_id], [InStockQuantity]) values 
     (101, 3)
    ,(102, 1)
    ,(103, 7)
    ;
    
    select original_orderline_count.Order_id 
    /*first table gets each order with it's line count*/
    from (select order_line.Order_id, count(order_line.OrderLine_id) as line_count
            from test_OrderLine order_line
            group by order_line.Order_id) as original_orderline_count
    /*second table gets count of order lines in stock by order*/
    inner join (select ol.Order_id, count(ol.OrderLine_id) as line_count
                from test_Order o
                inner join test_OrderLine ol on o.Order_id = ol.Order_id
                inner join test_Item i on i.Item_id = ol.Item_id
                where ol.Quantity <= i.InStockQuantity
                group by ol.Order_id) as orderline_in_stock
    /*join the two tables on order id line count matching*/         
    on original_orderline_count.Order_id = orderline_in_stock.Order_id
    and original_orderline_count.line_count = orderline_in_stock.line_count
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-15
      • 2014-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多