如何在SQL中间隙不超过3的其他列中的一列上查找元素

时间:2019-02-05 09:55:59

标签: mysql sql mysql-8.0

我有一个SQL视图,说emp_table,看起来像下面这样:

+----------+----------+------+
| actor_id | movie_id | year |
+----------+----------+------+
|        2 |   280088 | 2002 |
|        2 |   396232 | 2000 |
|        3 |   376687 | 2000 |
|        4 |   336265 | 2001 |
|        5 |   135644 | 1953 |
|        6 |    12083 | 1996 |
|        7 |   252053 | 1993 |
|        7 |   402635 | 1992 |
|        7 |   409592 | 1995 |
|        8 |   101866 | 2000 |
|        9 |   336265 | 2001 |
|       10 |    12148 | 2000 |
|       11 |    80189 | 2001 |
|       12 |    12148 | 2000 |
|       13 |    80189 | 2001 |
|       14 |    70079 | 1982 |
|       15 |    12148 | 2000 |
|       16 |   242675 | 1991 |
|       17 |   105231 | 1993 |
|       17 |   242453 | 1988 |
+----------+----------+------+

...等等。我需要找到所有从未有超过3年职业间隔的actor_id。这意味着我需要计算所有演员,如果我计算出他们在电影中所扮演的独特年份的数量,然后对其进行排序,那么一年之间的最大连续差异永远不会超过3年。 请帮我这个SQL查询。我已经尝试过SQL自连接,但是对此再也想不了。

所有SQL代码仅适用于MySQL。

注意,您可以考虑只有actor_id和movie_id的一种组合。

预期结果

+----------+----------+
| actor_id | max_gap  |
+----------+----------+
|        2 |   2      |
|        3 |   0      |
|        4 |   0      |
|        5 |   0      |
|        6 |   0      |
|        7 |   2      |
|        . |   .      |
|        . |   .      |
|        . |   .      |
|       17 |   5      |
+----------+----------+

依此类推

注释2:很抱歉,输出中有太多更改。这是最终版本,此后不再更改。

3 个答案:

答案 0 :(得分:2)

我最初是从一种反联接方法开始的,但是在看到您对最大间隙的要求后就对其进行了更改。

以下方法从子查询开始,该子查询本身使用相关子查询为每个参与者记录和年份计算前瞻性年份差距。然后由演员进行汇总,并断言从未发生过3年以上的差距。

SELECT actor_id, MAX(gap) AS max_gap
FROM
(
    SELECT
        e1.actor_id,
        ABS(e1.year - COALESCE((SELECT e2.year FROM emp_table e2
                       WHERE e2.actor_id = e1.actor_id AND e2.year > e1.year
                       ORDER BY e2.year LIMIT 1), e1.year)) AS gap
    FROM emp_table e1
) t
GROUP BY
    actor_id
HAVING
    MAX(gap) <= 3;

请注意,由于演员最近一年的情况不佳,因此致电COALESCE是非常必要的。在这种情况下,没有前瞻性的年份,但我们希望在今年进行折扣。

答案 1 :(得分:2)

使用 MySQL 8 MariaDB 10.2 ,您可以使用窗口功能 LEAD()获取下一个连续的游戏年份演员(或最后一个演员为LAG())。然后,您只需要在外部查询中获得最大差异即可。

with tmp as (
  select 
      actor_id,
      year,
      lead(year) over (partition by actor_id order by year) as year_lead
  from emp_table e
)
select actor_id, coalesce(max(year_lead - year), 0) as max_gap
from tmp
group by actor_id
having max_gap <= 3;

演示:https://www.db-fiddle.com/f/cWChT2TqLuRT8bW1zcM9G2/0

答案 2 :(得分:1)

通过actor_id对表和组进行自我连接:

select
  e1.actor_id, max(coalesce(e2.year, e1.year) - e1.year) max_gap
from emp_table e1 left join emp_table e2
on 
  e2.actor_id = e1.actor_id
  and 
  e2.year = (
    select min(year) from emp_table where actor_id = e1.actor_id and year > e1.year
  )
group by e1.actor_id  
having max_gap <= 3

请参见demo