了解子查询

时间:2014-11-06 16:44:54

标签: sql join

我最初希望看到每个供应商(通过分销商)与每个客户完成的总美元业务的细分,我试图不使用内部联接语法并使用下面的查询为此目的:

select customers.cust_id, Vendors.vend_id, sum(quantity*item_price) as total_business from
(((Vendors left outer join Products 
on Products.vend_id = Vendors.vend_id)
left outer join OrderItems --No inner joins allowed
on OrderItems.prod_id = Products.prod_id)
left outer join Orders 
on Orders.order_num = OrderItems.order_num)
left outer join Customers 
on Customers.cust_id = Orders.cust_id
where Customers.cust_id is not null -- THE ONLY DIFFERENCE BETWEEN QUERY1 AND QUERY2
group by Customers.cust_id, Vendors.vend_id
order by total_business

现在,我正在尝试查看所有供应商 - 客户组合的查询输出结果,包括那些没有业务交易且我尝试通过单个SQL查询编写此组合的组合。我的老师提供了这个解决方案,但实际上我根本无法理解逻辑,因为我从未遇到过子查询。

select 
    customers.cust_id, 
    Vendors.vend_id, 
    sum(OrderItems.quantity*orderitems.item_price) 
    from
      (
        customers 
         inner join 
        Vendors on 1 = 1
      ) 
     left outer join --synthetic product using joins
      (
        orders 
         join 
        orderitems on orders.order_num = OrderItems.order_num
         join 
        Products on orderitems.prod_id = products.prod_id
      ) on 
        Vendors.vend_id = Products.vend_id and 
        customers.cust_id = orders.cust_id
group by customers.cust_id, vendors.vend_id
order by customers.cust_id

非常感谢

1 个答案:

答案 0 :(得分:0)

我会将此查询编写为:

select c.cust_id, v.vend_id, coalesce(cv.total, 0)
fro Customers c cross join
    Vendors v left outer join
    (select o.cust_id, v.vend_id, sum(oi.quantity * oi.item_price) as total
     from orders o join 
          orderitems oi
          on o.order_num = oi.order_num join
          Products p
          on oi.prod_id = p.prod_id
     group by o.cust_id, v.vend_id
    ) cv
    on cv.vend_id = v.vend_id and 
       cv.cust_id = c.cust_id
order by c.cust_id;

结构非常相似。两个版本都是从所有客户和供应商之间创建交叉产品开始的。这将在输出结果集中创建所有行。接下来,需要在此级别计算聚合。在上面的查询中,这是作为子查询显式完成的,该子查询将值聚合到客户/供应商级别。 (在原始查询中,这是在外部查询中完成的。)

最后一步是将这些加在一起。

您的老师应该鼓励您使用表别名,尤其是表缩写。您还应该被鼓励使用正确的join。因此,虽然您可以将cross join表示为inner join on 1=1,但cross join是SQL语言的一部分,而不是黑客。

同样,from子句中的括号可能会使逻辑更难理解。显式子查询更容易阅读。