SQL-创建具有多个联接的视图的问题

问题描述 投票:0回答:2

我需要创建一个SQL视图,将每个电影的以下信息相关联:

1)电影的放映次数

2)每次电影放映中的预告片数量及其长度

3)每次电影放映中出现的斑点数量及其长度

我为请求的时间长而对不起,但我试图做到更加清晰。

我有这些表:

FILM-> id_film主键

id_film    film_title 
1          'Iron Man'
2          'Spider Man'
3          'Thor'

Screening_film-> id_screening主键,id_film外键引用电影(id_film)

id_screening   id_film
1               1
2               2
3               3
4               3

SPOT-> id_spot主键

id_spot       lenght
1               10
2               20
3               30

TRAILER-> id_trailer主键

id_trailer     lenght
4               10
5               20
6               30

Spot_trailer_screening->此表中有现货/预告片和电影之间的关联

id_ST          id_film
1               1
2               2
3               3
4               1
5               2
6               3

这是我的代码:

CREATE VIEW film_list AS
SELECT f.film_title, 
count(x.id_screening) number_of_screening, count (s.id_spot) num_spot, 
sum(s.lenght) spot_lenght, count(t.id_trailer) num_trailer, 
sum(t.lenght) trailer_lenght
FROM film f
FULL OUTER JOIN screening_film x
ON x.id_film = f.id_film
FULL OUTER JOIN spot_trailer_screening y --The problems begin with this join, the count of number_of_screening isn't correct--
ON y.id_film = f.id_film
FULL OUTER JOIN spot s
ON s.id_spot = y.id_st
FULL OUTER JOIN trailer t
ON t.id_trailer = y.id_st
GROUP BY f.id_film, f.film_title;

输出:

FILM_TITLE      NUMBER_OF_SCREENING NUM_SPOT SPOT_LENGHT  NUM_TRAILER TRAILER_LENGHT
  Iron Man            2                1         10          1            10
  Spider Man          2                1         20          1            20
  Thor                4                2         60          2            60

正确的输出应该是以下内容:

FILM_TITLE      NUMBER_OF_SCREENING NUM_SPOT SPOT_LENGHT  NUM_TRAILER TRAILER_LENGHT
  Iron Man            1                1         10          1            10
  Spider Man          1                1         20          1            20
  Thor                2                1         30          1            30
sql oracle join view
2个回答
1
投票

大量示例数据(第1至32行)使查询时间很长。当然,您拥有这些表,因此您的“实际”查询从第33行开始。

接下来的3个CTE(第34-53行)(t_screeningt_spott_trailer)用于计算所需的一切,并避免在查询中获得duplicate值。

最后,最后一个查询(从第55行开始)仅连接已计算的内容。如果有些电影没有预告片或斑点,则必须使用外部连接。但是,由于示例数据表明有所不同,因此我使用了内部联接。

正如我所说:相当长的查询,所以我将其分为3部分以提高可读性:

样本数据:

SQL> with
  2  -- sample data
  3  film (id_film, film_title) as
  4    -- I wish I were 12 again ... I'd LOVE these films
  5    (select 1, 'Iron Man'   from dual union all
  6     select 2, 'Spider Man' from dual union all
  7     select 3, 'Thor'       from dual
  8    ),
  9  screening_film (id_screening, id_film) as
 10    (select 1, 1 from dual union all
 11     select 2, 2 from dual union all
 12     select 3, 3 from dual union all
 13     select 4, 3 from dual
 14    ),
 15  spot (id_spot, length) as
 16    (select 1, 10 from dual union all
 17     select 2, 20 from dual union all
 18     select 3, 30 from dual
 19    ),
 20  trailer (id_trailer, length) as
 21    (select 4, 10 from dual union all
 22     select 5, 20 from dual union all
 23     select 6, 30 from dual
 24    ),
 25  spot_trailer_screening (id_st, id_film) as
 26    (select 1, 1 from dual union all
 27     select 2, 2 from dual union all
 28     select 3, 3 from dual union all
 29     select 4, 1 from dual union all
 30     select 5, 2 from dual union all
 31     select 6, 3 from dual
 32    ),

计算:

 33  -- calculation
 34  t_screening as
 35    (select s.id_film,
 36            count(*) cnt_screening
 37     from screening_film s join film f on f.id_film = s.id_film
 38     group by s.id_film
 39    ),
 40  t_spot as
 41    (select sts.id_film,
 42            count(*) cnt_spot,
 43            sum(s.length) len_spot
 44     from spot_trailer_screening sts join spot s on sts.id_st = s.id_spot
 45     group by sts.id_film
 46    ),
 47  t_trailer as
 48    (select sts.id_film,
 49            count(*) cnt_trailer,
 50            sum(t.length) len_trailer
 51     from spot_trailer_screening sts join trailer t on sts.id_st = t.id_trailer
 52     group by sts.id_film
 53    )

最终查询:

 54  -- final query
 55  select f.id_film,
 56         f.film_title,
 57         c.cnt_screening,
 58         --
 59         s.cnt_spot,
 60         s.len_spot,
 61         --
 62         t.cnt_trailer,
 63         t.len_trailer
 64  from film f join t_screening c on c.id_film = f.id_film
 65              join t_spot s on s.id_film = f.id_film
 66              join t_trailer t on t.id_film = f.id_film
 67  order by f.id_film;

   ID_FILM FILM_TITLE CNT_SCREENING   CNT_SPOT   LEN_SPOT CNT_TRAILER LEN_TRAILER
---------- ---------- ------------- ---------- ---------- ----------- -----------
         1 Iron Man               1          1         10           1          10
         2 Spider Man             1          1         20           1          20
         3 Thor                   2          1         30           1          30

SQL>

0
投票

您的餐桌有问题。您必须标准化表Spot_trailer_screening。因为当您通过Film将该表与表id_film联接时,您的记录是重复的。您必须将表Spot_trailer_screening分为两个表Spot_screening(id_spot, id_film)Trailer_screening(id_trailer, id_film)。您将使用这两个表进行联接。

© www.soinside.com 2019 - 2024. All rights reserved.