[英]Complex SQL Query - Joining 5 tables with complex conditions
我有以下表格:预定,订单行,订单抬头,产品,客户。 这些表中的每一个仅作一点解释:
以下是具有相关字段和示例数据的表:
Reservation
bill-cust-key prod-key qty-reserved reserve-date
10000 20000 10 05/30/2014
10003 20000 5 06/20/2014
10003 20001 15 06/20/2014
10003 20001 5 06/25/2014
10002 20001 5 06/21/2014
10002 20002 20 06/21/2014
Order-Item
order-num cust-key prod-key qty-ordered
30000 10000 20000 10
30000 10000 20001 5
30001 10001 20001 10
30002 10001 20001 5
30003 10002 20003 20
Order-Header
order-num cust-key bill-cust-key order-date
30000 10000 10000 07/01/2014
30001 10001 10003 07/03/2014
30002 10001 10003 07/15/2014
30003 10002 10002 07/20/2014
Customer
cust-key cust-name
10000 Customer A
10001 Customer B
10002 Customer C
10003 Customer D
Product
prod-key prod-name
20000 Prod A
20001 Prod B
20002 Prod C
20003 Prod D
我试图写一个查询,向我显示预订表和订单项表中都存在的客户/产品组合。 一个小窍门是我们有一个客户和一个计费客户。 保留表和订单标题表都包含客户,但是订单项表仅包含客户。 结果应显示开票客户。 此外,对于同一客户/产品组合,可能会有几个预订和订单项,因此,我想显示保留数量和订购数量的总和。
下面是我想要的输出的示例:
bill-cust-key cust-name prod-key prod-name qty-ordered qty-reserved
10000 Customer A 20000 Prod A 10 10
10003 Customer D 20001 Prod B 15 20
这是我尝试过的查询,似乎对我不起作用。
SELECT customer.cust-key, customer.cust-name, product.prod-key, prod.prod-name,
SUM(order-item.qty-ordered), SUM(reservation.qty-reserved)
FROM ((reservation INNER JOIN order-item on reservation.prod-key = order-item.product-key)
INNER JOIN order-header on reservation.bill-cust-key = order-header.bill-cust-key and
order-item.order-num = order-header.order-num), customer, product
WHERE customer.cust-key = reservation.bill-cust-key
AND product.prod-key = reservation.prod-key
GROUP BY customer.cust-key, customer.cust-name, product.prod-key, product.prod-name
这么长的帖子我很抱歉! 我只是想确保我的基地覆盖了!
您想像这样联接表:
from reservation res join order-header oh on res.bill-cust-key = oh.bill-cust-key
join order-item oi on oi.order-num = oh.order-num
and oi.prod-key = res.prod-key
/* join customer c on c.cust-key = oi.cust-key old one */
join customer c on c.cust-key = oh.bill-cust-key
join product p on p.prod-key = oi.prod-key
我发现通过使用CROSS APPLY(或OUTER APPLY)或仅使用别名内部查询(如果您无权使用它们)将输出行与聚合行分开是非常有用的。
例如,
SELECT
customer.cust-key,
customer.cust-name,
tDetails.prod-key,
tDetails.prod-name,
tDetails.qty-ordered,
tDetails.qty-reserved
FROM customer
--note that this could be an inner-select table in which you join if not cross-join
CROSS APPLY (
SELECT
product.prod-key,
prod.prod-name,
SUM(order-item.qty-ordered) as qty-ordered,
SUM(reservation.qty-reserved) as qty-reserved
FROM reservation
INNER JOIN order-item ON reservation.prod-key = order-item.product-key
INNER JOIN product ON reservation.prod-key = product.prod-key
WHERE
reservation.bill-cust-key = customer.cut-key
GROUP BY product.prod-key, prod.prod-name
) tDetails
有很多方法可以对此进行切片,但是您以正确的方式说出“我想要返回什么记录集”。 我喜欢上面的内容,因为它可以帮助我直观地看到每个“查询”在做什么。 用CROSS套用标记的内部查询只是按产品订单和预订进行分组,但在外部最上面的查询中由当前客户过滤。
另外,我将联接保留在“ WHERE”子句之外。 使用'WHERE'子句进行非主键过滤(例如,cust-name ='Bob')。 我发现说一个是表联接很有帮助,“ WHERE”子句是一个属性过滤器。
TAKE 2-使用内联查询
这种方法仍然尝试获取具有不同产品的客户列表,然后使用该数据形成外部查询,您可以从中获取汇总。
SELECT
customer.cust-key,
customer.cust-name,
products.prod-key,
products.prod-name,
--aggregate for orders
( SELECT SUM(order-item.qty-ordered)
FROM order-item
WHERE
order-item.cust-key = customer.cust-key AND
order-item.prod-key = products.prod-key) AS qty-ordered,
--aggregate for reservations
( SELECT SUM(reservation.qty-reserved)
FROM reservations
--join up billingcustomers if they are different from customers here
WHERE
reservations.bill-cust-key = customer.cust-key AND
reservations.prod-key = products.prod-key) AS qty-reserved
FROM customer
--get a table of distinct products across orders and reservations
--join products table for name
CROSS JOIN (
SELECT DISTINCT order-item.prod-key FROM order-item
UNION
SELECT DISTINCT reservation.prod-key FROM reservations
) tDistinctProducts
INNER JOIN products ON products.prod-key = tDistinctProducts.prod-key
TAKE 3-派生表
根据一些快速查询,Progress DB确实支持派生表。 由于不需要进行分组,因此该方法已在很大程度上被“应用交叉”(或“应用外部”)取代。 但是,如果您的数据库仅支持这种方式,那就这样吧。
SELECT
customer.cust-key,
customer.cust-name,
products.prod-key,
products.prod-name,
tOrderItems.SumQtyOrdered,
tReservations.SumQtyReserved
FROM customer
--get a table of distinct products across orders and reservations
--join products table for name
CROSS JOIN (
SELECT DISTINCT order-item.prod-key FROM order-item
UNION
SELECT DISTINCT reservation.prod-key FROM reservations
) tDistinctProducts
INNER JOIN products ON products.prod-key = tDistinctProducts.prod-key
--derived table for order-items
LEFT OUTER JOIN ( SELECT
order-item.cust-key,
order-item.prod-key,
SUM(order-item.qty-ordered) AS SumQtyOrdered
FROM order-item
GROUP BY
order-item.cust-key,
order-item.prod-key) tOrderItems ON
tOrderItems.cust-key = customer.cust-key AND
tOrderItems.prod-key = products.prod-key
--derived table for reservations
LEFT OUTER JOIN ( SELECT
reservations.bill-cust-key,
reservations.prod-key,
SUM(reservations.qty-reserved) AS SumQtyReserved
FROM reservations
--join up billingcustomers if they are different from customers here
WHERE
reservations.bill-cust-key = customer.cust-key AND
reservations.prod-key = products.prod-key) tReservations ON
tReservations.bill-cust-key = customer.cust-key AND
tReservations.prod-key = products.prod-key
根据您的原始代码和要求,这是Progress解决方案的起点-
DEFINE VARIABLE iQtyOrd AS INTEGER NO-UNDO.
DEFINE VARIABLE iQtyReserved AS INTEGER NO-UNDO.
FOR EACH order-item
NO-LOCK,
EACH order-header
WHERE order-header.order-num = order-item.order-num
NO-LOCK,
EACH reservation
WHERE reservation.prod-key = order-item.prod-key AND
reservation.bill-cust-key = order-header.bill-cust-key
NO-LOCK,
EACH product
WHERE product.prod-key = reservation.prod-key
NO-LOCK,
EACH customer
WHERE customer.cust-key = reservation.bill-cust-key
NO-LOCK
BREAK BY customer.cust-key
BY product.prod-key
BY product.prod-name
:
IF FIRST-OF(customer.cust-key) OR FIRST-OF(product.prod-key) THEN
ASSIGN
iQtyOrd = 0
iQtyReserved = 0
.
ASSIGN
iQtyOrd = iQtyOrd + reservation.qty-ordered
iQtyReserved = iQtyReserved + reservation.qty-reserved
.
IF LAST-OF(customer.cust-key) OR LAST-OF(product.prod-key) THEN
DISPLAY
customer.cust-key
customer.cust-name
product.prod-key
prod.prod-name
iQtyOrd
iQtyReserved
WITH FRAME f-qty
DOWN
.
END.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.