2017-10-02 10 views
1

すべてのオーダー明細に在庫があるオーダーのOrder_IDのリストを返す単一のクエリが必要です。Transact SQLサブクエリ

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つのアイテムすべてがItemのInStockQuantity以下の数量を持ちます。
  • 1002の場合、アイテム101の数量は4ですが、在庫はわずか3です​​。
  • 1003の場合、アイテム104にアイテム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 

そのクエリの問題は、唯一の注文ラインのONEはそのORDER_IDが結果に表示するために数量< = InStockQuantityを持っている必要があることです注文のすべての数量が< = InStockQuantitiesの場合、結果に表示されます。

"ALL"演算子については読んでいますが、サブクエリでどのように動作するかはわかりません。

+1

order_idを入力として受け取り、次に各item_idを繰り返し処理し、要求量/注文数量を在庫数と照合する一時テーブルを作成する方法について説明します。 – Tingo

答えて

0

この問題について考えるには、在庫量よりも多い数量を必要とする注文行を持たない注文IDを返すことです。参加し​​3210あなたは、彼らが0の量を持っているかのように完全に在庫切れのアイテムを扱う可能性があり、左の使用:

not exists()を使用して
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)) 
+0

これは、サブクエリで 'と'を 'where'に変更した場合に機能します。今のように、(サブクエリ)はすべての 'order_id'を返します。 – SqlZim

+0

@SqlZim arg、そうです。ありがとうございました。 – Mureinik

0

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 | 
+----------+ 
0

ここにありますiddle: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