如何内连接多列?

时间:2015-05-05 04:20:54

标签: sql sql-server inner-join

我正在尝试为关键字搜索编写存储过程。我们设置数据库的方式。

有一个Genres表格有Genre namesGenre ID's,然后有一个Genrebridge表,其中包含genreID1, GenreID2, GenreID3, GenreID4, GenreID5, SongID, AlbumIDArtistID

如何内部加入每个GenreID字段,以便Genre name链接到Genre Bridge

ALTER PROCEDURE [dbo].[usp_album_search_keyword_AlbumNameANDArtistName]
(
    -- Add the parameters for the stored procedure here
    @albumname  varchar(255),
    @artistname varchar(255)
)
As
Begin
Select 
    Distinct a.AlbumTitle, art.ArtistName, a.AvgRatingNBR, a.OriginalPrice, a.DiscountPrice
FROM 
    Albums a 
    inner join Artists art on a.ArtistID = art.ArtistID
    inner join GenreBridge gb on gb.AlbumID = a.AlbumID
    inner join Genres g on g.GenreID = gb.GenreID1
    inner join genres g on g.GenreID = gb.genreID2
    inner join genres g on g.GenreID = gb.GenreID3
    inner join genres g on g.GenreID = gb.GenreID4
    inner join genres g on g.GenreID = gb.GenreID5

    where a.AlbumTitle like '%' + @albumname + '%' 
    and art.ArtistName like '%' + @artistname + '%'
End

2 个答案:

答案 0 :(得分:5)

除了使用注释中提到的相同别名外,表GenreBridge未正确标准化。要规范化表格,最好在表格上放置一个GenreID列,然后根据需要插入尽可能多的行来模拟专辑的所有类型。这也将解除对每张专辑类型数量的任意限制。

作为附注,您的原始程序似乎根本不使用Genre(在选择列表或过滤器中),因此无需加入它,您将不需要DISTINCT

正如您所注意到的,您现在面临联接问题,具体取决于AlbumGenre

上的有效流派列数

假设你一直使用INT主键,我会将表GenreBridge规范化为Albums和Genres之间的很多:很多链接表,同时将它重命名为AlbumGenre反映了许多:许多惯例,例如:

CREATE TABLE dbo.AlbumGenre
(
   AlbumId INT NOT NULL,
   GenreId INT NOT NULL,

   CONSTRAINT PK_AlbumnGenre PRIMARY KEY(AlbumId, GenreId),
   CONSTRAINT FK_AlbumnGenre_Albumn FOREIGN KEY(AlbumId) REFERENCES Albums(AlbumId),
   CONSTRAINT FK_AlbumnGenre_Genre FOREIGN KEY(GenreId) REFERENCES Genres(GenreId)
);

您的程序需要强制执行1到5种类型的限制(即在插入AlbumnGenre记录链接之前,确保此列的行少于5行。)

要列出相册的所有类型,您只需要将Albumn加入AlbumGenre并在where子句中按AlbumnId过滤(它将返回尽可能多的行数)是流派)。

如上所述,不需要DISTINCT或加入流派:

ALTER PROCEDURE [dbo].[usp_album_search_keyword_AlbumNameANDArtistName]
(
    -- Add the parameters for the stored procedure here
    @albumname  varchar(255),
    @artistname varchar(255)
)
As
Begin
Select a.AlbumTitle, art.ArtistName, a.AvgRatingNBR, a.OriginalPrice, a.DiscountPrice
FROM 
    Albums a 
    inner join Artists art on a.ArtistID = art.ArtistID
    where a.AlbumTitle like '%' + @albumname + '%' 
    and art.ArtistName like '%' + @artistname + '%'
End

答案 1 :(得分:1)

@StuartLC提供了一些我认真考虑的好反馈。但是,如果您打算保留数据库模式,那么此查询应该起作用:

SELECT          a.AlbumTitle, 
                art.ArtistName, 
                a.AvgRatingNBR, 
                a.OriginalPrice, 
                a.DiscountPrice,
                g1.GenreName,
                g2.GenreName,
                g3.GenreName,
                g4.GenreName,
                g5.GenreName
FROM            Albums a 
INNER JOIN      Artists art on a.ArtistID = art.ArtistID
INNER JOIN      GenreBridge gb on gb.AlbumID = a.AlbumID
LEFT OUTER JOIN Genres g1 on g1.GenreID = gb.GenreID1
LEFT OUTER JOIN Genres g2 on g2.GenreID = gb.GenreID2
LEFT OUTER JOIN Genres g3 on g3.GenreID = gb.GenreID3
LEFT OUTER JOIN Genres g4 on g4.GenreID = gb.GenreID4
LEFT OUTER JOIN Genres g5 on g5.GenreID = gb.GenreID5
WHERE           a.AlbumTitle like ('%' + @albumname + '%')
    AND         art.ArtistName like ('%' + @artistname + '%')