MySQL:通过多个表引用时返回多行

MySQL:通过多个表引用时返回多行,mysql,Mysql,我试图列出所有的商店销售的产品,其中包含特定的吉他配件的吉他钻机 我有一个guitarRig数据库。吉他装备有零件(即放大器,机柜,麦克风,吉他类型,吉他弦类型,跳线,效应器),这些零件来自从商店购买的产品。 购买产品的价格取决于我的采购信息表 这是我的桌子: Table Part: name guitarRig references GuitarRig(name) product references Product(name) Table Product:

我试图列出所有的商店销售的产品,其中包含特定的吉他配件的吉他钻机

我有一个
guitarRig
数据库。吉他装备有
零件(即
放大器
机柜
麦克风
吉他类型
吉他弦类型
跳线
效应器
),这些零件来自从商店购买的产品。 购买产品的价格取决于我的
采购信息

这是我的桌子:

Table Part:
    name
    guitarRig references GuitarRig(name)
    product references Product(name)

Table Product:
    name
    part references Part(name)
    barcodeNumber

Table PurchaseInformation:
    price
    product references Product(name)    
    purchasedFrom references Store(name)  
Table Store:
    name
    storeLocation

到目前为止,我得到的是:

SELECT p.name AS Part, prod.name AS Product, sto.name AS Store
FROM Part p, ProductInformation prod, Store sto, PurchaseInfo purch
WHERE   sto.storeNumber = purch.storeNumber
    AND purch.product = prod.name
    AND prod.Part = p.name
    AND p.name = 
    (
        SELECT name
        FROM Part
        WHERE name LIKE '%shielded%'
    )   
GROUP BY p.name;

我得到的错误是,它返回超过1行,然而,这是我想要的!我想列出销售包含我正在搜索的零件的产品的商店。

快速解决方法是将相等比较运算符(
=
)替换为
中的

    AND p.name IN 
    (
       SELECT name ...

我说这是快速修复,因为这将修复错误,但这不是编写查询的最有效方法。现在还不清楚您的查询是否会返回您指定或实际期望的结果集

我强烈建议您避免使用老式的逗号连接运算符,而是使用join关键字

将查询重新构造为等效查询会产生以下结果:

SELECT p.name AS Part
     , prod.name AS Product
     , sto.name AS Store
  FROM Part p
  JOIN ProductInformation prod
    ON prod.Part = p.name
  JOIN PurchaseInfo purch
    ON purch.product = prod.name
  JOIN Store sto
    ON sto.storeNumber = purch.storeNumber
 WHERE p.name IN
       (
         SELECT name
           FROM Part
          WHERE name LIKE '%shielded%'
       )
 GROUP BY p.name;
一些注释。
GROUPBY
子句将为每个不同的零件名称将所有连接行折叠为一行。也就是说,每个零件名称只返回一行

听起来这不是你想要的。我建议您删除该GROUP BY,并添加一个ORDER BY,至少在您弄清楚您得到的是什么结果集,以及您是否希望返回这些行之前

其次,在(子查询)
中使用
并不是最有效的方法。如果p.name与该子查询返回的值匹配,因为
p
是对同一
部分的引用,这:

 WHERE p.name IN
       (
         SELECT name
           FROM Part
          WHERE name LIKE '%shielded%'
       )
这其实是一种更复杂的表达方式:

 WHERE p.name LIKE '%shielded%' 

我想你真的想要这样的东西:

SELECT p.name     AS Part
     , prod.name  AS Product
     , sto.name   AS Store
  FROM Part p
  JOIN ProductInformation prod
    ON prod.Part = p.name
  JOIN PurchaseInfo purch
    ON purch.product = prod.name
  JOIN Store sto
    ON sto.storeNumber = purch.storeNumber
 WHERE p.name LIKE '%shielded%'
 ORDER BY p.name, prod.name, sto.name
这将返回
Part
中的所有行,其中包括名称中某处的字符串“shield”

我们将把这些行与
ProductInformation
中与该部分匹配的所有行进行匹配。(请注意,对于内部联接,如果
零件
产品信息
中没有至少一个匹配行,则不会返回
零件
中的该行。它将只返回在
产品信息
中找到至少一个“匹配”行的行。)

类似地,我们加入到PurchaseInfo中的匹配行,然后存储。同样,如果至少有一个
存储
中没有匹配行,我们将无法取回这些行。此查询只会返回至少与
存储
相关的
零件
的行。我们不会返回任何不在
存储

行可以以任何顺序返回,因此为了使结果集具有确定性,我们可以添加order BY子句。这不是必需的,它不影响返回的行,它只影响返回的行的顺序