【问题标题】:Oracle SQL using sub queriesOracle SQL 使用子查询
【发布时间】:2016-02-22 20:22:25
【问题描述】:

我在学习子查询时遇到了一些麻烦。我试图展示每个客户订购过的最昂贵的书,并使用不相关的子查询来完成。

这是我目前所拥有的:

select Firstname || ', '|| Lastname "Name", title, retail
from Customers join orders using (Customer#) join orderitems using (Order#)                 
join books using (Isbn)
where retail =ANY (select max(retail)
                from books join orderitems using (isbn) join Orders using (order#) join Customers using (Customer#)
                group by Customer#)                 
order by  Firstname, Lastname;

内部查询显示每个客户的最大零售额,但我不确定为什么外部查询会多次显示客户。我刚刚开始学习 SQL,任何帮助将不胜感激

【问题讨论】:

  • 您使用的是哪个 DBMS?甲骨文还是 MySQL? retail 列位于哪个表中? titlebooks 的一部分吗?
  • 这是使用 Oracle。书名和零售在书籍表中。 Customer# 和 first ,lastname 在 customers 下。

标签: oracle subquery correlated-subquery


【解决方案1】:
select Firstname || ', '|| Lastname "Name", title, retail
from Customers join orders using (Customer#) join orderitems using (Order#)                 
join books using (Isbn)
where (Customer#, retail) in (select Customer#,  max(retail)
                from books join orderitems using (isbn) join Orders using (order#) join Customers using (Customer#)
                group by Customer#)                 
order by  Firstname, Lastname;

或者我喜欢这样做的方式,而不是两次选择相同的东西:

select Name, title, Customer#, retail
from (select Firstname || ', '|| Lastname "Name", title, Customer#,  
             retail, max(retail) over (partition by  Customer#) max_retail
        from books 
        join orderitems using (isbn) 
        join Orders using (order#) 
        join Customers using (Customer#))    
where retail=max_retail             
order by  Firstname, Lastname;

【讨论】:

  • Tyvm 这很有效,帮助我理解了不同的做法。谢谢!
【解决方案2】:

这里的缺陷在于您的逻辑,而不是语法。内部查询返回每位客户的最高零售价,然后外部查询返回与这些价格之一匹配的任何连接行。考虑一下您有两个客户的情况 - 客户 1 进行购买,一个购买 10 美元,一个购买 20 美元,而客户 2 只购买了一次 10 美元。内部查询将返回 20$(客户 1 的最大购买量)和 10$(客户 2 的最大购买量),然后外部查询将返回 all 这些金额中的任何一个的购买量,即,所有三行。 “教科书”解决方案是 rank 每个客户的购买,并且只返回每个客户的前一个:

SELECT   name, title, retail
FROM     (SELECT firstname || ', '|| lastname AS name,
                 title, 
                 retail,
                 RANK() OVER (PARTITION BY customer# ORDER BY retail DESC) AS rk
          FROM   customers
          JOIN   orders USING (customer#)
          JOIN   orderitems USING (order#)                 
          JOIN   books USING (isbn))
WHERE    rk = 1
ORDER BY 1

【讨论】:

  • 只要 OP 实际上没有使用 MySQL 没有实现窗口函数:)
  • @ConsiderMe 根据他使用 Oracle 的 cmets。我想知道我是否应该相应地编辑问题的标签,或者将其留给 OP 以确保安全。
  • 一个不错的解决方案。获得最大的问题是,当有两个相同(价格)时。在您的解决方案中,您随机获得其中之一,我的解决方案同时显示了两者。这取决于,哪个更好。
  • 否则我可能错了。我从不使用rank()。我所说的,至少对row_number()是正确的
  • @a.j.tawleed 你错了 - 如果有不止一本书放在第一位,那么两者将具有相同的 rank()1,并且两者都会被退回。如果您确实只想返回其中一个,row_number() 可能更合适
【解决方案3】:
select 
  Firstname || ', '|| Lastname "Name"
  ,max(retail) "Most expensive book by customer"
from 
  Customers c, Orders o, OrderItems oi, Books b 
where c.customer#=o.customer# 
  and o.order#=oi.order# 
  and oi.isbn=b.isbn
group by Firstname || ', '|| Lastname;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-16
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多