2016-06-13 26 views
0

我有一個電影表和一個電影可以有一個previous_part。現在我想,例如,基於movie_id'412331'獲取所有電影,如圖像中顯示的星球大戰電影。這可能與SQL(MsSQL/AzureSql)?如何從指向同一個表中的實體的外鍵獲取所有實體?

我對缺乏信息感到抱歉,但我真的不知道如何甚至開始做這個問題的SQL查詢。

movies

更新:

創建一個遞歸查詢,但如果我給啓動它所有的(見代碼塊WHERE Prev.previous_part = 412332)電影它僅適用。所以在這個例子中,Episode V會返回另外兩部電影,而Episode VI只會返回Episode VII。

With MovieList AS 
    (SELECT Prev.movie_id, Prev.title, Prev.description, Prev.previous_part, 1 as PrevLevel 
    FROM Movie as Prev 
    WHERE Prev.previous_part = 412332 

    UNION ALL 

    SELECT Mov.movie_id, Mov.title, Mov.description, Mov.previous_part, ML.PrevLevel + 1 
    FROM Movie as Mov 
    INNER JOIN MovieList AS ML 
    ON Mov.previous_part = ML.movie_id 
    WHERE Mov.previous_part IS NOT NULL) 
SELECT * FROM MovieList 
+0

[使用公用表表達式遞歸查詢(https://technet.microsoft.com /en-us/library/ms186243(v=sql.105).aspx])。 – Igor

+0

我喜歡這裏的前傳如何不存在:) 鑑於你有一個publication_year,但是,也許你想要一個名爲類似'franchise','family'或'series'的字段來代替,然後只顯示記錄在發佈順序中具有相同的系列值(如果有)。 –

+0

@JoelCoehoorn問題是,我正在使用像這樣構建的現有數據庫。電影表甚至有大約380000條記錄。 –

回答

2

這是遞歸的CTE你需要:

;with ml as (
--this is Anckor Query 
select movie_id, title, previous_part 
from movie where movie_id = 412325 
union all 
--this is Recursive Query 
select m.movie_id, m.title, m.previous_part 
from movie m 
inner join ml on ml.previous_part = m.movie_id --link current prev to parent id 
--if you want sequels instead of prev's change to m.previous_part = ml.movie_id 
) 
select * from ml 
0

@Igors評論是否正確遞歸查詢如果有多個引用/ heirarchy級別可以使用遞歸公用表表達式。微軟有一個很好的經理/員工示例。 https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx

這可能比你想要的要複雜得多,有點不清楚。

如果它只是一個參考級別,這意味着您不必匹配,然後一次又一次匹配找到您想要的所有內容,您可以使用自引用外連接。

SELECT * 
FROM 
    dbo.movies m1 
    LEFT JOIN dbo.movies m2 
    ON m1.movied_id = m2.previous_part 
WHERE 
    m1.title LIKE '%Star Wars%' 
    OR m2.movied_ID IS NOT NULL 
    OR m2.title LIKE '%Star Wars%' 

良好的第一刺我覺得你很接近。沒有你的數據集有點難,但是這裏有一個編輯應該給你一個每部電影和他們的級別的完整列表。

;With MovieList AS (
    SELECT Prev.movie_id, Prev.title, Prev.description, Prev.previous_part, 1 as PrevLevel 
    FROM Movie as Prev 
    WHERE Prev.previous_part IS NULL 

    UNION ALL 

    SELECT Mov.movie_id, Mov.title, Mov.description, Mov.previous_part, ML.PrevLevel + 1 
    FROM Movie as Mov 
    INNER JOIN MovieList AS ML 
    ON Mov.previous_part = ML.movie_id 
) 
SELECT * FROM MovieList 

注意您可以在SELECT * FROM MovieList添加一個WHERE語句來限制列表中,但是你想你生成層次結構之後。

+0

不幸的是我必須匹配,然後再匹配一次。 –

+0

發佈的MS鏈接會讓您在那裏僅將previous_part視爲示例中的Manager,將movie_id視爲Employee。 SQLauthority在同一主題上也可能稍微容易消化文章。 http://blog.sqlauthority.com/2012/04/24/sql-server-introduction-to-hierarchical-query-using-a-recursive-cte-a-primer/ – Matt

+0

我跟着它,但當前的查詢如果給定的movie_id開頭是專營權中的第一個,我只做了作品。所以最早的movie_id。 –

0

這似乎解決了你的問題。

select * 
into #t 
from (
select 123 id,'xxx'nm,1234 pid 
union all 
select 1234, 'xl',12345 
union all 
select 12345,'xlxl',123456 
) x 

declare @mid int = 123 

select x.* from #t x 
where x.id = @mid 

union all 

select y.* from #t x 
left join #t y 
on x.pid = y.id 
where x.id = @mid 

union all 

select z.* from #t x 
left join #t y 
on x.pid = y.id 
left join #t z 
on y.pid = z.id 
left join #t xx 
on z.pid = xx.id 
where x.id = @mid 

union all 

select xx.* from #t x 
left join #t y 
on x.pid = y.id 
left join #t z 
on y.pid = z.id 
left join #t xx 
on z.pid = xx.id 
where x.id = @mid 

此查詢拉至4部電影,但你可以添加更多的邏輯如下。 也只有在您按照最早的電影ID進行搜索時纔有效。 如果你需要它來搜索兩種方式這應該工作

declare @mid int = 12345 

select distinct * from 
(
select x.* from #t x 
where x.id = @mid 

union all 

select y.* from #t x 
left join #t y 
on x.pid = y.id or x.id = y.pid 
where x.id = @mid 

union all 

select z.* from #t x 
left join #t y 
on x.pid = y.id or x.id = y.pid 
left join #t z 
on y.pid = z.id or y.id = z.pid 
where x.id = @mid 

union all 

select xx.* from #t x 
left join #t y 
on x.pid = y.id or x.id = y.pid 
left join #t z 
on y.pid = z.id or y.id = z.pid 
left join #t xx 
on z.pid = xx.id or z.id = xx.pid 
where x.id = @mid 

) x 
相關問題