【问题标题】:SQL querying from multiple tables and retrieving dataSQL 从多个表中查询并检索数据
【发布时间】:2021-04-16 04:49:35
【问题描述】:

我有以下以架构形式表示的表格:

  • 客户(cid:整数,cname:字符串,评级:整数,薪水:真实)
  • 项目(iid:整数,iname:字符串,类型:字符串)
  • 订单(cid:整数,iid:整数,日:日期,数量:真实)

问题是我不知道如何从多个表中搜索数据并在我的软件界面中表示它。虽然我可以表示它,但我无法从表中检索数据。所以,这里是我需要获取的数据。

我必须去取:

  1. 订购了 ID 为 100 的商品的客户的姓名。
  2. 订购了笔记本电脑(即“笔记本电脑”类型的商品)的客户的姓名。
  3. 订购了笔记本电脑和台式电脑的客户。已订购所有商品的客户姓名

谢谢

【问题讨论】:

  • 使用连接请查看示例链接link
  • 看起来你只是把你的作业丢给我们了。 @Andreas 很友好地解决了这个问题,但为了将来参考,我建议您阅读并注意 stackoverflow.com/help/minimal-reproducible-example。在要求家庭作业答案之前,请展示您自己尝试过的内容,然后询问您遇到的具体问题。当有人给你一个银盘上的答案时,你什么也学不到。

标签: sql database oracle


【解决方案1】:

您的问题:

  1. 订购了 id 为 100 的商品的客户的姓名。

    select name from customer where cid in (select distinct(cid) from order where iid= 100) ;

  2. 订购了笔记本电脑(即“笔记本电脑”类型的物品)的客户的姓名。

    select name from customer where cid in (select distinct(cid) from order where iid=(select iid from item where type='laptop')) ;

  3. 订购了笔记本电脑和台式电脑的客户。 已订购所有商品的顾客姓名

    select name from customer where cid in (select distinct(cid) from order where iid in (select iid from item where type in ('laptop','desktop') )) ;

【讨论】:

  • 1) DISTINCT 不是函数,删除 ( ) 括号。 --- 2) IN 子句隐含DISTINCT,所以去掉多余的DISTINCT 关键字。 --- 3) #2 失败如果有多个itemtype = 'laptop'(对此投反对票) --- 4) #3 失败 无效使用IN 子句。应该是type in ('laptop', 'desktop')(对此投反对票) --- 5) 查询将返回不正确的结果,因为它会返回订购笔记本电脑的客户台式机,但只应退回订购both的客户。 (对此投反对票)
  • 是的,你是对的 #1 上面的查询只是针对 postgresql 的示例,而在 postgres 中 distinct 是一个函数。 #2这是基于一个项目退出笔记本电脑类型的假设,查询可以根据业务逻辑进行更改#3任何人都可以根据他们的数据库和业务用例更改查询,上面的查询只是给出了一个想法,一个人可以如何处理这些数据类型和根据变化用例的变化,谢谢评论
  • 我坚持我所说的:DISTINCT 不是函数,即使在 PostgreSQL 中也不是。当然,PostgreSQL 确实有一个 extension,在 DISTINCT 关键字之后有一个 ON ( ... ) 子句,但 ON 关键字意味着 ( ) 不是函数参数语法。 --- select distinct(cid) 实际上是 select distinct (cid)select distinct cid 相同,除了列已从简单的列名更改为表达式。表达式语法允许使用 ( ) 括号,而不是 DISTINCT 语法。
  • 我坚持我对 #2 所说的话:如果我订购了 2 台不同的笔记本电脑,即不仅仅是一个 qty = 2,那么内部选择返回 2 个 iid 值,因为 SQL 使用 iid=(...) ,而不是iid in (...),查询将失败并显示“选择返回多行”。
  • 我支持 #3 的反对票,因为有缺陷的查询的答案没有用。您不能只给出一个错误的答案并说“哦,好吧,您需要自己修复语法错误和查询逻辑”。那肯定没用。如果您懒得展示好的有效示例,那实际上可能是人们可以根据他们的数据模型进行调整的东西,那么就不要费心回答了。是的,业务用例发生变化,示例必须相应调整,但至少显示有效的语法和结构。
【解决方案2】:
  1. 订购了 ID 为 100 的商品的客户的姓名。

我们可以通过首先运行查询来查找包含给定商品 ID 的订单的客户 ID,然后查找客户姓名。这是通过IN 子句完成的。

SELECT c.cname
  FROM Customer c
 WHERE c.cid IN (
          SELECT o.cid
            FROM Order o
           WHERE o.iid = 100
       )

一个客户只会被返回一次,这是由 IN 子句的 Set 语义保证的,但如果数据库允许多个客户具有相同的名称,则可能会多次返回相同的客户名称。

要只返回一次客户名称,即使有多个同名客户,我们也可以使用DISTINCT 子句。如果这样做,我们可以将查询更改为使用普通的JOIN

SELECT DISTINCT c.cname
  FROM Order o
  JOIN Customer c ON c.cid = o.cid
 WHERE o.iid = 100

哪个更好取决于口味,我相信它们的表现大致相同。就个人而言,我更喜欢第一个。


  1. 订购了笔记本电脑(即“笔记本电脑”类型的商品)的客户的姓名。

与以前相同,但针对Item 表使用WHERE 条件。

SELECT c.cname
  FROM Customer c
 WHERE c.cid IN (
          SELECT o.cid
            FROM Item i
            JOIN Order o ON o.iid = i.iid
           WHERE i.type = 'laptop'
       )
SELECT DISTINCT c.cname
  FROM Item i
  JOIN Order o ON o.iid = i.iid
  JOIN Customer c ON c.cid = o.cid
 WHERE i.type = 'laptop'

  1. 订购了笔记本电脑和台式电脑的客户。
    已订购所有商品的客户姓名

当使用IN 子句时,我们只需要执行两次,即可找到同时订购的客户。

SELECT c.cname
  FROM Customer c
 WHERE c.cid IN (
          SELECT o.cid
            FROM Item i
            JOIN Order o ON o.iid = i.iid
           WHERE i.type = 'laptop'
       )
   AND c.cid IN (
          SELECT o.cid
            FROM Item i
            JOIN Order o ON o.iid = i.iid
           WHERE i.type = 'desktop'
       )

对于另一种方式,我们需要使用GROUP BY 而不是DISTINCT,以便我们可以检查客户是否同时订购了两者。

SELECT DISTINCT c.cname
  FROM Item i
  JOIN Order o ON o.iid = i.iid
  JOIN Customer c ON c.cid = o.cid
 WHERE i.type IN ('laptop', 'desktop')
 GROUP BY c.cid, c.cname
HAVING COUNT(DISTINCT i.type) = 2

或者我们可以混合两种风格。

SELECT c.cname
  FROM Customer c
 WHERE c.cid IN (
          SELECT o.cid
            FROM Item i
            JOIN Order o ON o.iid = i.iid
           WHERE i.type IN ('laptop', 'desktop')
           GROUP BY o.cid
          HAVING COUNT(DISTINCT i.type) = 2
       )

第三个可能是性能最好的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多