我需要帮助创建一个复杂的SQL查询

时间:2017-01-25 18:05:13

标签: sql oracle

我需要帮助创建复杂的SQL查询。考虑以下表格(例如简化):

列表

list_id | user_id | list_type
-----------------------------------
1       | 1       | favorite movies
2       | 2       | favorite movies

list_items

list_id | movie_id 
------------------
1       | 1
2       | 1
2       | 2

在此示例中,用户1已将电影1添加到他最喜欢的电影列表中。用户2已将电影1和电影2添加到他最喜欢的电影列表中。

我正在尝试输出所有其他电影的列表,每个添加了电影1的用户也会添加到他们喜欢的电影列表中,按频率排序。结果应该是:

movie_id | total_adds
---------------------
2        | 1

我有问题掌握如何使用COUNT和DISTINCT生成此输出,以及我是否可以以某种方式加入以减少处理开销。

2 个答案:

答案 0 :(得分:3)

这是一种方法。

with
     test_data ( user_id, movie_id ) as (
       select 1, 1 from dual union all
       select 2, 1 from dual union all
       select 2, 2 from dual union all
       select 2, 3 from dual union all
       select 3, 2 from dual union all 
       select 3, 3 from dual union all
       select 4, 1 from dual union all
       select 4, 2 from dual union all
       select 4, 9 from dual
     )
--  End of test data (NOT part of the SQL query).
--  Solution (SQL query) begins BELOW THIS LINE. Use your actual table and column names.
select   movie_id, count(*) as ct
from     test_data
where    user_id in ( select user_id from test_data where movie_id = 1 )
  and    movie_id != 1
group by movie_id
order by ct desc, movie_id
;

  MOVIE_ID         CT
---------- ----------
         2          2
         3          1
         9          1

4 rows selected.

答案 1 :(得分:0)

这是另一种方式。它有点复杂,但取决于数据通常会更快:

WITH lists ( list_id, user_id ) AS (
      SELECT 1, 1 FROM dual UNION ALL
      SELECT 2, 2 FROM dual UNION ALL
      SELECT 3, 2 FROM dual UNION ALL
      SELECT 4, 2 FROM dual UNION ALL
      SELECT 5, 3 FROM dual UNION ALL 
      SELECT 6, 3 FROM dual UNION ALL
      SELECT 7, 4 FROM dual UNION ALL
      SELECT 8, 4 FROM dual UNION ALL
      SELECT 9, 4 FROM dual
  ), list_items (list_id, movie_id) AS (
      SELECT 1, 1 FROM dual UNION ALL
      SELECT 2, 1 FROM dual UNION ALL
      SELECT 3, 2 FROM dual UNION ALL
      SELECT 4, 3 FROM dual UNION ALL
      SELECT 5, 2 FROM dual UNION ALL 
      SELECT 6, 3 FROM dual UNION ALL
      SELECT 7, 1 FROM dual UNION ALL
      SELECT 8, 2 FROM dual UNION ALL
      SELECT 9, 9 FROM dual
  ), test_data (user_id, movie_id) AS (
     SELECT user_id, movie_id FROM lists l
     JOIN list_items li ON l.list_id=li.list_id
  )
SELECT movie_id, count(*) ct
FROM (
   SELECT user_id, movie_id, min(movie_id) OVER (PARTITION BY User_Id) min_movie_id
      , SUM(CASE WHEN movie_id = 1 THEN 0 ELSE 1 END) OVER (PARTITION BY user_id) ct
   FROM test_data 
)
WHERE min_movie_id=1 AND movie_id<>1
GROUP BY movie_id
ORDER BY ct desc, movie_id
;

测试数据扩展回原始表格。结果与mathguy相同。