在 mySQL 的嵌套子查询中 SELECT 多列的推荐方法

Recommended method to SELECT multiple columns within a nested subquery in mySQL

在嵌套子查询中选择多列推荐使用哪些方法?自从我对任何查询进行编码以来已经有一段时间了,而且我很难解决这个问题。具体挑战在下面代码的第 2 行。 IN 操作数在这里不太有效 (请参阅下面的错误消息),我不确定这是否只是我使用的语法问题,and/or 有一个更好的方法来解决这个问题(即使用 HAVING 操作数或 JOIN 语句)

SELECT * FROM Rules WHERE Rules.LNRule_id 
    IN(SELECT LNRule_id1,LNRule_id2,LNRule_id3,LNRule_id4 FROM Silhouette
    WHERE Silhouette.Silhouette_Skirt=(SELECT Silhouette_Skirt FROM Style
        WHERE Style.Style_Skirt='$Style_Skirt')
    )

此查询的目的是 SELECT table Rules 中的所有相关行以获得 table Style 中的特定值(即 $Style_Skirt),它通过将它与几个因素之一匹配来实现 - 在本例中是服装的 Silhouette。因此,我在这部分查询中尝试做的是 SELECT table Rules 中的所有行,谁的 ID (LNRule_id) 匹配任何指定列中的值tableSilhouette

(SELECT LNRule_id1,LNRule_id2,LNRule_id3,LNRule_id4 FROM Silhouette WHERE Silhouette.Silhouette_Skirt=(...)) 

编辑 存在多对多关系(每个Silhouette有多个适用的Rules,每个Rule可以应用于多个Silhouettes)。所有规则都驻留在table 'Rules' (每行一个),并且每个规则都有一个id('LNRule_id'). table 'Silhouette' 的列告诉它哪些行需要从 'Rules' 调用 'LNRule_id' (LNRule_id1,2,3, 4 指示应调用哪些规则,并将相关行的 id 值存储在 table 'Rules')


当前由 IN 操作数生成的错误消息是:

SQLSTATE[21000]: Cardinality violation: 1241 Operand should contain 1 column(s)

mysql 抱怨在 IN 的一侧只有一个列,而在另一侧有一个多列行集。为了使 IN 运算符起作用,IN 右侧的行集必须与左侧的列数完全相同;在这种情况下,一列。

如果您执行 WHERE LNRule_id IN( SELECT LNRule_Id1 ...) OR LNRule_id IN( SELECT LNRule_Id2 ...) OR ... OR ... 之类的操作,您可能会实现您想要完成的目标,但生成的查询将是一个怪物,其性能将是可怕的。可能还有其他方法可以解决这个问题,但您尝试的任何方法都可能同样残酷。

我没有足够的信息来绝对确定我在说什么,但在我看来,您遇到此问题的原因是您的数据库架构未规范化。通常,每当您看到 table 中的一组列的名称都以相同的前缀开头并以数字结尾时,这意味着某人在某个地方没有规范化他们的数据。

为了解决您问题中的编辑问题,您所实现的在概念上可能是多对多关系,但就关系数据库而言,(您知道,科学、理论、既定实践、使事情真正起作用所必需的方法,)它是绝对不是多对多关系。多对多关系肯定 不是 用 column1,column2,column3,... columnN 实现的。为确保我没有编造这些东西,您可以在此处阅读其他人对多对多关系的看法:

Many-to-many relations in RDBMS databases

所以,如果我正确理解发生了什么,我的建议是引入一个新的 table,称为 SilhouetteRules,它包含两列,silhouette_id 和 rule_id . table 将在剪影和您的规则之间实现多对多关系。然后你当然会从 Silhouette 中删除所有 rule1、rule2、rule3 等列。

完成后,您可以使用如下查询获取所有轮廓和与之关联的所有规则:

SELECT * FROM Silhouette 
    LEFT JOIN SilhouetteRules ON 
        Silhouette.id = SilhouetteRules.silhouette_id 
    LEFT JOIN Rules ON 
        SilhouetteRules.rule_id = Rules.id 

以上查询将为每个轮廓生成多行,其中轮廓字段在每一行中都是相同的,只有规则字段不同。不要对此感到惊讶,这就是关系数据库的工作方式。

给定一个 given_silhouette_id,您可以使用如下查询检索与其关联的所有规则:

SELECT * FROM Rules
    LEFT JOIN SilhouetteRules ON 
         Rules.id = SilhouetteRules.rule_id 
WHERE 
    SilhouetteRules.silhouette_id = given_silhouette_id

因此,您将使用此查询作为查询中的子查询,例如问题中的查询。

现在,关于问题中的查询,我无法确切地告诉您需要如何修改它才能使其与我建议的规范化一起工作,因为我无法理解它。你看,即使你解决了目前 SELECT * FROM table WHERE single-column IN multi-column-rowset 的问题,下面还有另一个问题:WHERE Silhouette.Silhouette_Skirt=(SELECT ... 部分也不起作用,因为你无法将列的值与select 语句的结果。所以,我不知道你想在那里做什么。希望一旦您规范化您的架构并修复查询的第一个问题,那么第二个问题的解决方案就会变得显而易见,或者您可以在 Whosebug 上提出另一个问题。

P.S。米海的回答有用吗?

我想你想要这个查询

SELECT * FROM  Rules r
JOIN Silhouette s
(ON r.LNRule_id=s.LNRule_id1
OR r.LNRule_id=s.LNRule_id2
OR r.LNRule_id=s.LNRule_id3
OR r.LNRule_id=s.LNRule_id4)
JOIN Style st
ON s.Silhouette_Skirt=st.Silhouette_Skirt
WHERE st.Silhouette_Skirt = '$Style_Skirt'