2012-03-21 87 views
2

我需要能够使用简单搜索来搜索我的数据库的SQL查询。这里是我现在的表格:搜索多个表(SQL)

Table artists 
-------------- 
id 
name 

Table albums 
------------- 
id 
artistID 
name 

Table songs 
------------ 
id 
albumID 
name 

我该如何去做这件事?以下是我尝试过的一些SQL查询,但我的问题是它返回了很多数据。例如,如果我搜索像Snoop Dogg这样的艺术家,那么即使他们不包含他的名字,它也会为每张专辑和歌曲返回一行。

SELECT * FROM artist,album,songs WHERE artist.name LIKE '%snoop%' OR albums.name LIKE '%snoop%' OR songs.name LIKE '%snoop%'; 

编辑:

这里是一个示例数据库;

artists 
----------- 
1 | Snoop Dogg 
2 | Linkin Park 

albums 
-------- 
1 | artist=1 | Boom 
2 | artist=2 | ThisIsIt 

songs 
-------- 
1 | album=1 | First 
2 | album=2 | Second Linkin 
3 | album=2 | Third 
4 | album=1 | Fourth 

所以我想为“窥探”的搜索只返回艺术家“史努比狗狗”。但随后像“Linkin”这样的搜索将返回艺术家和歌曲。

+0

表歌没有'artistID'? – safarov 2012-03-21 23:51:35

+0

@safarov他们没有,但我可以添加它。 – Flipper 2012-03-21 23:53:06

+0

如果没有,那么你如何检测哪首歌属于艺术家 – safarov 2012-03-21 23:54:02

回答

3

这个查询将检索匹配的艺术家,歌曲和专辑查询搜索。第一列给出了关于数据来源的线索,第二列是id,最后一个是名字。

select 'Artists' OriginatingTable, id, name 
    from artists 
where name like '%snoop%' 
union all 
select 'Albums', id, name 
    from albums 
where name like '%snoop%' 
union all 
select 'Songs', id, name 
    from songs 
where name like '%snoop%' 
+0

这工作完美!谢谢! – Flipper 2012-03-22 01:22:31

2

您需要将所有数据连接在一起,以便它成为一个大数据集,允许您一次查询所有字段。要做到这一点,你想使用left join这是最适合这种情况。

SELECT * 
FROM songs 
LEFT JOIN albums 
ON songs.albumID = albums.id 
LEFT JOIN artists 
ON albums.artistID = artists.id 
WHERE artist.name LIKE '%snoop%' 
OR albums.name LIKE '%snoop%' 
OR songs.name LIKE '%snoop%'; 

A union也可以使用,但这可能不会给你你想要的结果。左连接会为每首与艺术家,专辑或歌曲匹配的歌曲添加一行。工会会为每首歌曲提供一行,使其与歌曲名称匹配,每张专辑的行与专辑名称匹配,并且每位艺术家的行与艺术家姓名相匹配。

-1

这对歌手名,歌曲名和专辑名称

SELECT artist.name,albums.name,songs.name 
FROM songs 
LEFT JOIN album ON album.id = song.albumID 
LEFT JOIN artists ON album.artistID = artists.id 
WHERE 
artist.name LIKE '%snoop%' OR albums.name LIKE '%snoop%' OR songs.name LIKE '%snoop%' 
4

下使用UNION,从而避免JOIN S:

(
    SELECT 
     'artist' as `type`, 
     `artists`.`id` as `id`, 
     `artists`.`name` as `name` 
    FROM `artists` 
    WHERE 
     `artists`.`name` LIKE '%snoop%' 
) 
UNION 
(
    SELECT 
     'album' as `type`, 
     `albums`.`id` as `id`, 
     `albums`.`name` as `name` 
    FROM `albums` 
    WHERE 
     `albums`.`name` LIKE '%snoop%' 
) 
UNION 
(
    SELECT 
     'song' as `type`, 
     `songs`.`id` as `id`, 
     `songs`.`name` as `name` 
    FROM `songs` 
    WHERE 
     `songs`.`name` LIKE '%snoop%' 
) 
+0

有类型的列也在选择是一个非常好的想法.. – 2012-03-22 00:27:55

+0

当我尝试这个时得到了这个错误:#1064 - 你的SQL语法错误;检查与您的MySQL服务器版本相对应的手册,以找到在'WHERE'artists'附近使用的正确语法。'name' LIKE'%snoop')第6行的UNION(SELECT) – Flipper 2012-03-22 01:05:15

+0

此外,在Nikola的答案中,OriginatingTable中的类型如何区分? – Flipper 2012-03-22 01:05:39

0

你应该从每个表中选择和结果的返回和工会,但请记住,所有的选择必须返回相同的号码,种类的列。

SELECT 'Artist' as kind, id as artistId, name, null as albumId, null as SongId 
FROM artist WHERE artist.name LIKE '%snoop%' 
union 
SELECT 'Album', artistId, name, id, null FROM album WHERE albums.name LIKE '%snoop%' 
union 
SELECT 'Song', albums.artistId, songs.name, songs.albumId, songs.id 
FROM songs inner join albums on songs.albumId = albums.id 
WHERE songs.name LIKE '%snoop%' 

这样会避免所有表的组合,你也有各行中的所有可用信息。