为什么此SQL查询会永远运行?

时间:2019-05-22 08:34:18

标签: sql sqlite

我正试图找到“找到一连三年没有失业的演员”。

表架构如下

--------------------   -----------------------   ----------------------
|   Movie          |   |     Person           |  |       Cast         |
--------------------   ------------------------  ----------------------
| MovieID  | year  |   |  PersonID  | Gender  |  | MovieID | PersonID |
--------------------   ------------------------  ----------------------

我尝试加入并进行子查询。但是我的SQL语句在sqlite上永远运行

SELECT DISTINCT TRIM(A.PID), A.NAME FROM PERSON A 
WHERE TRIM(A.PID) NOT IN (

SELECT DISTINCT TRIM(B.PID) FROM M_CAST B, MOVIE C WHERE TRIM(B.MID) = 
TRIM(C.MID) AND EXISTS (

SELECT TRIM(D.MID) FROM M_CAST D, MOVIE E WHERE TRIM(D.MID) = TRIM(E.MID) 
AND TRIM(B.PID) = TRIM(D.PID) AND (CAST (SUBSTR(TRIM(E.YEAR), 
LENGTH(TRIM(E.YEAR)) -3 , 4) AS INT) - 3) >

CAST (SUBSTR(TRIM(C.YEAR), LENGTH(TRIM(C.YEAR)) -3 , 4) AS INT) AND NOT 
EXISTS (

SELECT TRIM(F.MID) FROM M_CAST F, MOVIE G WHERE TRIM(F.MID) = (G.MID) AND 
TRIM(B.PID) = TRIM(F.PID) AND 
CAST (SUBSTR(TRIM(C.YEAR), LENGTH(TRIM(C.YEAR)) -3 , 4) AS INT) < CAST 
(SUBSTR(TRIM(G.YEAR), LENGTH(TRIM(G.YEAR)) -3 , 4) AS INT) AND
CAST (SUBSTR(TRIM(G.YEAR), LENGTH(TRIM(G.YEAR)) -3 , 4) AS INT) < CAST 
(SUBSTR(TRIM(E.YEAR), LENGTH(TRIM(E.YEAR)) -3 , 4) AS INT)
)

)

)




CAST (SUBSTR(TRIM(C.YEAR), LENGTH(TRIM(C.YEAR)) -3 , 4) AS INT) #was used 
since the year had some special characters and was used to extract only the 
last 4 digits (year)

预期结果是显示未失业3年以上但我的查询一直运行且没有结果的演员的所有姓名。

1 个答案:

答案 0 :(得分:0)

这是一个棘手的问题。在最新版本的SQLite中使用窗口函数要容易得多。

这是一种方法:

  • 获取一个人工作的所有年份的明确列表。
  • 使用此列表查找连续工作三年(即给定年份加上接下来的两年)的人员。
  • 选择不在此列表中的所有人。

您可以在这里停止并自己解决问题。作为社论评论,使用窗口功能将更加简单。但是只有最新版本的SQLite支持这些功能。

剧透:

with py as (
      select distinct c.personid, m.year
      from cast c join
           movie m
           on c.movieid = m.movieid
     ),
     py3 as (
      select distinct py.personid
      from py join
           py py1
           on py1.personid = py.personid and
              py1.year = py.year + 1 join
           py py2
           on py2.personid = py.personid and
              py2.year = py.year + 2
     )
select p.*
from person p
where not exists (select 1
                  from py3
                  where py3.personid = p.personid
                 );

Here是db <>小提琴,它说明代码有效。 (没有数据,只是证明代码正确。)