如何使用 Mysql Joins 而不是嵌套子查询来实现相同的结果?
Posted
技术标签:
【中文标题】如何使用 Mysql Joins 而不是嵌套子查询来实现相同的结果?【英文标题】:How to achieve the same result using Mysql Joins instead of nested subqueries? 【发布时间】:2016-12-17 16:24:27 【问题描述】:我有一些嵌套的子查询,结果非常慢,我正在努力用 mysql Joins 重写相同的代码,希望有人能帮助我。 我想从数据库中的所有歌曲中获取数据,除了播放列表中的歌曲,之后我只想要播放列表中的歌曲。 在这里你可以看到我的查询
提前致谢。
查询
$sql1 = "Select distinct title, artist, album from songs where id not in(Select id from songs where id
IN(Select id from songs where title IN(Select title from songs where id
IN(Select song_id from playlist where playlist_id IN (Select playlist_id from playlists where name = '$playlist_name')))))";
$sql2 = "Select distinct title, artist, album from songs where id in(Select id from songs where id
IN(Select id from songs where title IN(Select title from songs where id
IN(Select song_id from playlist where playlist_id IN (Select playlist_id from playlists where name = '$playlist_name')))))";
数据库设计
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
CREATE TABLE IF NOT EXISTS playlist (
playlist_id int(11) NOT NULL,
track_id int(11) NOT NULL,
song_id int(11) NOT NULL,
votes int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=1463 DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS playlists (
playlist_id int(11) NOT NULL,
`name` varchar(60) NOT NULL,
created_at datetime NOT NULL,
updated_at datetime NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS songs (
id int(11) NOT NULL,
path varchar(100) NOT NULL,
artist varchar(60) NOT NULL,
title varchar(60) NOT NULL,
album varchar(50) NOT NULL,
added_at datetime NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=3759 DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS users (
userID int(11) NOT NULL,
voices int(11) NOT NULL,
pass varchar(18) NOT NULL,
created_at datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE playlist
ADD PRIMARY KEY (track_id), ADD KEY song_id (song_id), ADD KEY playlist_id (playlist_id);
ALTER TABLE playlists
ADD PRIMARY KEY (playlist_id);
ALTER TABLE songs
ADD PRIMARY KEY (id), ADD UNIQUE KEY title (title,artist,album);
ALTER TABLE users
ADD PRIMARY KEY (userID);
ALTER TABLE playlist
MODIFY track_id int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=1463;
ALTER TABLE playlists
MODIFY playlist_id int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=14;
ALTER TABLE songs
MODIFY id int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3759;
ALTER TABLE users
MODIFY userID int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE playlist
ADD CONSTRAINT playlist_ibfk_1 FOREIGN KEY (song_id) REFERENCES songs (id) ON DELETE CASCADE,
ADD CONSTRAINT playlist_ibfk_2 FOREIGN KEY (playlist_id) REFERENCES playlists (playlist_id) ON DELETE CASCADE;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
【问题讨论】:
【参考方案1】:您可以将查询更改为,
数据库中的所有歌曲,除了播放列表中的歌曲
$sql1 = "Select distinct title, artist, album
from songs where id not in(Select distinct song.id
from songs song inner join playlist playlist
on playlist.song_id=song.id
inner join playlists playlists
on playlists.playlist_id=playlist.playlist_id
and playlists.name = '$playlist_name')";
播放列表中的那些,
$sql2 = "Select distinct song.title, song.artist, song.album
from songs song inner join playlist playlist
on playlist.song_id=song.id
inner join playlists playlists
on playlists.playlist_id=playlist.playlist_id
and playlists.name = '$playlist_name'";
【讨论】:
如果对您有帮助,请接受它作为答案@Mori Ruec以上是关于如何使用 Mysql Joins 而不是嵌套子查询来实现相同的结果?的主要内容,如果未能解决你的问题,请参考以下文章