SQL - Where...In 子句中的选择联合

SQL - Union of Selects inside Where... In clauses

(第一次post来这里,希望post不是傻事。不想看正文就看代码吧,代码结构简单问题,我想)

所以,今天我不得不进行一个查询,让我知道哪些演员在与特定演员相同的场景中出演(在电影数据库的上下文中)。我认为 table 细节不重要(但如果它们是我可以 post )。

在编写我的查询时,我意识到首先我必须对两个查询的结果执行 Union(这给了我场景所属的脚本的 ID ,以及该脚本中场景的顺序),然​​后 select 这些场景中的所有演员。场景分为Action Parts和Speech Lines,Actor只连接到那些而不是直接连接到场景。

我已经有了一个有效的答案(我仍然需要做另一个联合,但这很简单),但我想了解为什么它有效以及为什么我的第一个答案无效。我唯一做的就是删除括号。

所以这个答案行不通

Select Distinct name
From Staff S
Inner join MChar_ActPart MCAP on S.stid=MCAP.aid
Where (sid, sord) in ((Select Distinct sid, sord
                       From MChar_SpLine MCSL
                       Inner join Staff S on MCSL.aid = S.stid
                       Where name = 'John Idle')                     
                      Union 
                      (Select Distinct sid, sord
                       From MChar_ActPart MCAP
                       Inner join Staff S on MCAP.aid = S.stid
                       Where name = 'John Idle'))
And name != 'John Idle';

我收到这个错误。 “SQL 错误 (1064):您的 SQL 语法有误;请查看与您的 MariaDB 服务器版本对应的手册,了解在第 9 行 'Union (Select Distinct sid, sordFrom MChar_ActPart MCAPInner join Staff S ' 附近使用的正确语法

但是这个确实有效:

Select Distinct name
From Staff S
Inner join MChar_ActPart MCAP on S.stid=MCAP.aid
Where (sid, sord) in (Select Distinct sid, sord
                      From MChar_SpLine MCSL
                      Inner join Staff S on MCSL.aid = S.stid
                      Where name = 'John Idle'
                      Union 
                      Select Distinct sid, sord
                      From MChar_ActPart MCAP
                      Inner join Staff S on MCAP.aid = S.stid
                      Where name = 'John Idle')
And name != 'John Idle';

唯一不同的是括号。为什么一个有效,另一个无效?

unionselect distinct 是多余的。我强烈建议您将查询写成:

Select Distinct name
From Staff S Inner join
     MChar_ActPart MCAP 
     on S.stid = MCAP.aid
Where ((sid, sord) in (Select sid, sord
                       From MChar_SpLine MCSL Inner Join
                            Staff S
                            on MCSL.aid = S.stid
                       Where name = 'John Idle'
                      ) or
       (sid, sord) in (Select sid, sord
                       From MChar_ActPart MCAP Inner Join
                            Staff S
                            on MCAP.aid = S.stid
                       Where name = 'John Idle'
                      )
      ) and
      name <> 'John Idle';

这个版本还有更多的优化空间。

您看到的错误与 MariaDB 上的错误有关,当您执行 ((SELECT ...) UNION (SELECT ...)).

您可以查看此 link 上的错误状态:https://jira.mariadb.org/browse/MDEV-10028

注意:将此添加为答案,我认为这是对您所面临的特定错误的正确答案。

2*哎哟。

WHERE (a,b) ...没有优化好;避免它。

IN ( SELECT ... ) 现在经常优化得很好;避免它。

使用 'derived subquery' 将查询翻转过来,从而避免两个问题:

SELECT ...
    FROM ( ( SELECT sid, sord FROM ... )
           UNION ALL  -- or DISTICT
           ( SELECT sid, sord FROM ... )
         ) AS u
    JOIN ... AS x
        ON x.sid = u.sid
       AND x.sord = u.sord
    ...