我有一个正在处理的媒体中心网站,该网站有一个显示媒体类别的页面。每个类别可以分配有多个媒体项,并且每个媒体项可以分配给多个类别。
该页面包含一个文本输入,该输入必须能够过滤显示的类别。
我需要做的是获取与当前用户 ( $user_id
) 关联的每个类别以及属于该用户的媒体项目(未显示的类别不显示)。通常这很简单,但我还必须能够根据与媒体关联的其他表中的字段过滤类别。
我需要能够应用文本过滤器的字段如下:
message_number
在media
表中keywords
在media
表中speaker_name
在media_speakers
表中series_name
在media_series
表中book_name
在media_books
表中category_name
在media_categories
表中
就像现在一样,查询需要几秒钟才能完成。我不是 MySQL 专业人士,所以我确信必须有更好的方法来做我需要做的事情。如果有帮助,我正在通过 PHP 使用 MySQLi。我的查询有几个子查询,我很肯定这是问题的原因,但我不知道有什么其他方法可以做我想做的事情。
下面是相关的表结构和当前查询。我已经包含了尽可能多的信息,可以帮助某人帮助我解决这个问题,但如果您需要更多信息,请告诉我。
该media
表(省略了一些不相关的字段)(series、speaker 和 book 字段包含相应表中记录的 ID):
`id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`date` date NOT NULL DEFAULT '0000-00-00',
`message_number` varchar(32) DEFAULT NULL,
`series` int(10) unsigned zerofill NOT NULL DEFAULT '0000000000',
`speaker` int(10) unsigned zerofill NOT NULL DEFAULT '0000000000',
`book` int(10) unsigned zerofill NOT NULL DEFAULT '0000000000',
`keywords` text NOT NULL,
PRIMARY KEY (`id`)
表media_series
:
`id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`series_name` varchar(255) NOT NULL DEFAULT '',
`cover` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
表media_speakers
:
`id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`speaker_name` varchar(255) NOT NULL DEFAULT '',
`cover` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
表media_books
:
`id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,
`book_name` varchar(64) NOT NULL DEFAULT '',
`book_shortname` varchar(10) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
表media_categories
:
`id` int(10) unsigned zerofill NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`category_name` varchar(255) NOT NULL DEFAULT '',
`cover` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`)
表media_categories_assoc
:
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned DEFAULT NULL,
`media_id` int(10) unsigned zerofill DEFAULT NULL,
`category_id` int(10) unsigned zerofill DEFAULT NULL,
`marked_for_deletion` int(1) DEFAULT '0',
PRIMARY KEY (`id`)
最后,过于复杂的查询:
SELECT media_categories.id `media_categories.id`,
media_categories.user_id `media_categories.user_id`,
media_categories.category_name `media_categories.category_name`,
media_categories.cover `media_categories.cover`,
(SELECT id
FROM media
WHERE user_id = '$user_id'
AND media_categories.id IN (SELECT category_id
FROM media_category_assoc
WHERE user_id = '$user_id')
ORDER BY `date` DESC
LIMIT 1) `media.id`,
(SELECT `date`
FROM media
WHERE user_id = '$user_id'
AND media_categories.id IN (SELECT category_id
FROM media_category_assoc
WHERE user_id = '$user_id')
ORDER BY `date` DESC
LIMIT 1) `media.date`,
(SELECT series
FROM media
WHERE user_id = '$user_id'
AND media_categories.id IN (SELECT category_id
FROM media_category_assoc
WHERE user_id = '$user_id')
ORDER BY `date` DESC
LIMIT 1) `media.series`,
(SELECT speaker
FROM media
WHERE user_id = '$user_id'
AND media_categories.id IN (SELECT category_id
FROM media_category_assoc
WHERE user_id = '$user_id')
ORDER BY `date` DESC
LIMIT 1) `media.speaker`
FROM media_categories
LEFT JOIN media
ON media.id IN (SELECT media_id
FROM media_category_assoc
WHERE media_id = media.id
AND user_id = '$user_id')
LEFT JOIN media_series
ON media.series = media_series.id
LEFT JOIN media_speakers
ON media.speaker = media_speakers.id
LEFT JOIN media_books
ON media.book = media_books.id
WHERE media_categories.user_id = '$user_id'
AND media_categories.id IN (SELECT category_id
FROM media_category_assoc
WHERE user_id = '$user_id')
AND ( media.title LIKE '%filter_text%'
OR media.message_number LIKE '%filter_text%'
OR media.keywords LIKE '%filter_text%'
OR media_speakers.speaker_name LIKE '%filter_text%'
OR media_categories.category_name LIKE '%filter_text%'
OR media_series.series_name LIKE '%filter_text%'
OR media_books.book_name LIKE '%filter_text%' )
GROUP BY `media_categories.id`
ORDER BY `media.date` DESC
LIMIT 0, 12;