单个查询中的MySQL项及其属性
我创建了MySQL数据模型来存储内容及其自定义属性/字段。下面是它的简化版本 一个用于存储内容:单个查询中的MySQL项及其属性,mysql,sql,join,pivot-table,entity-attribute-value,Mysql,Sql,Join,Pivot Table,Entity Attribute Value,我创建了MySQL数据模型来存储内容及其自定义属性/字段。下面是它的简化版本 一个用于存储内容: CREATE TABLE `cms_content` ( `id` int(11) NOT NULL, `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `content_type_id` int(6) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unic
CREATE TABLE `cms_content` (
`id` int(11) NOT NULL,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`content_type_id` int(6) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `cms_content`
ADD PRIMARY KEY (`id`),
ADD KEY `content_type_id` (`content_type_id`);
第二个用于内容类型(如文章、电影、人物):
自定义字段:
CREATE TABLE `cms_custom_field` (
`id` int(11) NOT NULL,
`name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`content_type_id` int(6) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `cms_custom_field`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `name` (`name`,`content_type_id`),
ADD KEY `name_2` (`name`);
最后一个用于连接自定义字段和数据:
CREATE TABLE `cms_content_data` (
`id` int(11) NOT NULL,
`custom_field_id` int(11) NOT NULL,
`content_id` int(11) NOT NULL,
`value` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`value_content_id` int(11) DEFAULT NULL,
`value_taxonomy_value_id` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `cms_content_data`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `key` (`value`,`content_id`,`custom_field_id`) USING BTREE,
ADD KEY `content_id` (`content_id`),
ADD KEY `custom_field_id` (`custom_field_id`),
ADD KEY `value` (`value`),
ADD KEY `value_content_id` (`value_content_id`),
ADD KEY `value_taxonomy_value_id` (`value_taxonomy_value_id`),
ADD KEY `custom_field_id_2` (`custom_field_id`,`content_id`);
挑战
我需要创建一个查询来获取特定类型的内容及其所有自定义字段。
注意!这里的一个技巧是,一个自定义字段可以有多个content\u数据
值。
例如,一部电影有一个字段类型
,它可以在内容\u数据
中有多行
非工作查询
我能够动态生成以下查询:
SELECT
`content`.`id` AS `_content_id`,
`content`.`title` AS `_content_title`,
`content_data_0`.`value_taxonomy_value_id` AS `genres`,
`content_data_1`.`value_content_id` AS `production_company`,
`content_data_2`.`value` AS `date_released`,
`content_data_3`.`value` AS `runtime`,
`content_data_4`.`value` AS `tagline`,
`content_data_5`.`value` AS `imdb_rating`,
`content_data_6`.`value` AS `rt_rating`,
`content_data_7`.`value` AS `imdb_id`,
`content_data_8`.`value` AS `trailer_url`,
`content_data_9`.`value` AS `api_id`,
`content_data_10`.`value_taxonomy_value_id` AS `rating`,
`content_data_11`.`value` AS `revenue`,
`content_data_12`.`value` AS `poster_original_path`,
`content_data_13`.`value` AS `rt_rating_users`,
`content_data_14`.`value` AS `rt_url`,
`content_data_15`.`value` AS `rt_consensus`,
`content_data_16`.`value` AS `mc_rating`,
`content_data_17`.`value` AS `year`,
`content_data_18`.`value` AS `budget`,
`content_data_19`.`value_taxonomy_value_id` AS `original_language`,
`content_data_20`.`value_taxonomy_value_id` AS `production_countries`,
`content_data_21`.`value` AS `original_title`
FROM `cms_content` AS `content`
INNER JOIN cms_content_type ON cms_content_type.id = content.content_type_id
INNER JOIN `cms_content_data` AS `content_data_0` ON `content_data_0`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_1` ON `content_data_1`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_2` ON `content_data_2`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_3` ON `content_data_3`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_4` ON `content_data_4`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_5` ON `content_data_5`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_6` ON `content_data_6`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_7` ON `content_data_7`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_8` ON `content_data_8`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_9` ON `content_data_9`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_10` ON `content_data_10`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_11` ON `content_data_11`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_12` ON `content_data_12`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_13` ON `content_data_13`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_14` ON `content_data_14`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_15` ON `content_data_15`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_16` ON `content_data_16`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_17` ON `content_data_17`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_18` ON `content_data_18`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_19` ON `content_data_19`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_20` ON `content_data_20`.`content_id` = `content`.`id`
INNER JOIN `cms_content_data` AS `content_data_21` ON `content_data_21`.`content_id` = `content`.`id`
INNER JOIN `cms_content_type` AS `content_type` ON `content_type`.`id` = `content`.`content_type_id`
WHERE `content_type`.`name` = 'movie'
AND `content_data_0`.`custom_field_id` = 141
AND `content_data_1`.`custom_field_id` = 143
AND `content_data_2`.`custom_field_id` = 144
AND `content_data_3`.`custom_field_id` = 146
AND `content_data_4`.`custom_field_id` = 148
AND `content_data_5`.`custom_field_id` = 154
AND `content_data_6`.`custom_field_id` = 155
AND `content_data_7`.`custom_field_id` = 156
AND `content_data_8`.`custom_field_id` = 158
AND `content_data_9`.`custom_field_id` = 159
AND `content_data_10`.`custom_field_id` = 162
AND `content_data_11`.`custom_field_id` = 163
AND `content_data_12`.`custom_field_id` = 164
AND `content_data_13`.`custom_field_id` = 174
AND `content_data_14`.`custom_field_id` = 175
AND `content_data_15`.`custom_field_id` = 176
AND `content_data_16`.`custom_field_id` = 177
AND `content_data_17`.`custom_field_id` = 185
AND `content_data_18`.`custom_field_id` = 184
AND `content_data_19`.`custom_field_id` = 186
AND `content_data_20`.`custom_field_id` = 187
AND `content_data_21`.`custom_field_id` = 188
DESC LIMIT 100
这里的问题是:
1.返回错误。显然,由于每个content\u数据可以有多个值,MySQL以各种方式将它们组合在一起,最后我得到了一个movie
和各种自定义字段组合。
2.查询速度非常慢(可能是因为许多联接以及字段值的组合)
问题
MySQL(当然还有一些PHP后端魔术)中有没有任何方法可以在一个查询中返回所有必需的数据?考虑到当前的数据模型
对于多行,在逗号分隔的字段值中使用值对我来说是可行的(除非有更好的方法)
或者这个数据模型只是有缺陷,我需要以某种方式对其进行更改
提前谢谢 您需要条件聚合。我认为这是:
SELECT c.id as `_content_id`,
c.title AS `_content_title`,
FROM content c LEFT JOIN
(SELECT ct.content_id,
MAX(CASE WHEN ct.custom_field_id = 141 THEN ct.value_taxonomy_value_id END as genres,
MAX(CASE WHEN ct.custom_field_id = 143 THEN ct.value_taxonomy_value_id END as production_company,
MAX(CASE WHEN ct.custom_field_id = 144 THEN ct.value END as date_released,
. . .
FROM cms_content_type ct
GROUP BY ct.content_id
) ct
ON ct.content_id = c.contentId;
注意:value
并没有用于所有列,这似乎很奇怪。如果给定的内容\u id
有多行,且具有相同的客户字段\u id
,则可能需要组\u CONCAT()。使用这种技术,需要一个连接,然后条件聚合表达式提取期望值
对于您的quer,它看起来像:
SELECT
c.id content_id
c.title content_title,
MAX(CASE WHEN d.custom_field_id = 141 THEN d.value END) genres,
MAX(CASE WHEN d.custom_field_id = 143 THEN d.value END) production_company,
MAX(CASE WHEN d.custom_field_id = 144 THEN d.value END) date_released
...
FROM cms_content c
INNER JOIN cms_content_type t ON t.id = c.content_type_id
INNER JOIN cms_content_data d ON d.content_id = c.id
WHERE t.name = 'movie'
GROUP BY c.id, c.title
内容真的可以有多种类型吗?什么是value\u content\u id
和value\u taxonomy\u value\u id
?@Nick 1)对一种内容类型进行一次查询2)值是自由格式文本(例如标题、正文、日期),值\u content\u id与另一种内容相关,值\u taxonomy\u id与分类相关(例如,提供多种选择的类型)。我提出后者并不是为了简化问题。现在您可以看到EAV架构模式有多么糟糕。是的,这解决了结果问题,但查询本身仍然非常慢。即使使用了所有索引。我猜,我只需要进行第二次查询。无论如何,谢谢!是的,这解决了结果问题,但查询本身仍然非常慢。Even和所有索引。猜猜,我只需要进行第二次查询。不过谢谢你的帮助!
SELECT
c.id content_id
c.title content_title,
MAX(CASE WHEN d.custom_field_id = 141 THEN d.value END) genres,
MAX(CASE WHEN d.custom_field_id = 143 THEN d.value END) production_company,
MAX(CASE WHEN d.custom_field_id = 144 THEN d.value END) date_released
...
FROM cms_content c
INNER JOIN cms_content_type t ON t.id = c.content_type_id
INNER JOIN cms_content_data d ON d.content_id = c.id
WHERE t.name = 'movie'
GROUP BY c.id, c.title