繁体   English   中英

复杂的SQL查询-连接5个具有复杂条件的表

[英]Complex SQL Query - Joining 5 tables with complex conditions

我有以下表格:预定,订单行,订单抬头,产品,客户。 这些表中的每一个仅作一点解释:

  • 保留包含计费客户/产品组合的“保留”。
  • Order-Lines包含订单的行项目详细信息,包括订购的产品和数量。
  • Order-Header包含订单的标题信息,包括日期,客户和开票客户
  • 产品包含产品详细信息
  • 客户包含客户详细信息。

以下是具有相关字段和示例数据的表:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM