Php 显示同一行项目的某些特征(位于单独的表中)
我有一个MySQL数据库,存储人员及其相关特征 人员表:Php 显示同一行项目的某些特征(位于单独的表中),php,mysql,sql,database,Php,Mysql,Sql,Database,我有一个MySQL数据库,存储人员及其相关特征 人员表: +----+--------+ | id | name | +----+--------+ | 1 | Bella | | 2 | Jacob | | 3 | Edward | | 4 | Renée | | 5 | Alice | +----+--------+ 功能表: +----+----------+ | id | name | +----+----------+ | 1 | Bravery |
+----+--------+
| id | name |
+----+--------+
| 1 | Bella |
| 2 | Jacob |
| 3 | Edward |
| 4 | Renée |
| 5 | Alice |
+----+--------+
功能表:
+----+----------+
| id | name |
+----+----------+
| 1 | Bravery |
| 2 | Shyness |
| 3 | Kindness |
| 4 | Madness |
+----+----------+
个人特征表:
+-----------+------------+-------+
| person_id | feature_id | value |
+-----------+------------+-------+
| 1 | 1 | 50 |
| 1 | 2 | 84 |
| 1 | 4 | 10 |
| 2 | 1 | 8 |
| 2 | 2 | 78 |
| 2 | 4 | 41 |
| 3 | 3 | 27 |
| 4 | 1 | 36 |
| 4 | 3 | 64 |
| 5 | 2 | 78 |
| 5 | 3 | 2 |
+-----------+------------+-------+
比如说,我想要所有人的名单,按羞怯、善良和幽默的降序排列
勇敢(每个人都有这些特征的价值):
我当前使用此动态生成的查询:
SELECT person.name, pf2.value, pf3.value, pf1.value
FROM person
LEFT JOIN person_features pf2 ON person.id = pf2.person_id AND pf2.feature_id = 2
LEFT JOIN person_features pf3 ON person.id = pf3.person_id AND pf3.feature_id = 3
LEFT JOIN person_features pf1 ON person.id = pf1.person_id AND pf1.feature_id = 1
ORDER BY pf2.value DESC, pf3.value DESC, pf1.value DESC, person.name;
但是它有很多特性,速度有点慢,因为我必须为每个特性添加一个左连接。那么,有没有一种方法可以使用更通用的静态查询而不是动态查询?即使这意味着在我的PHP脚本中进行后处理来重新组合数据
创建语句:
CREATE TABLE `feature` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
CREATE TABLE `person_features` (
`person_id` int(11) NOT NULL,
`feature_id` int(11) NOT NULL,
`value` int(11) NOT NULL,
PRIMARY KEY (`person_id`,`feature_id`),
KEY `feature_id` (`feature_id`),
CONSTRAINT `person_features_ibfk_1` FOREIGN KEY (`person_id`) REFERENCES `person` (`id`),
CONSTRAINT `person_features_ibfk_2` FOREIGN KEY (`feature_id`) REFERENCES `feature` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
解释结果:
+----+-------------+--------+--------+--------------------+---------+---------+----------------------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+--------+--------------------+---------+---------+----------------------+------+---------------------------------+
| 1 | SIMPLE | person | ALL | NULL | NULL | NULL | NULL | 5 | Using temporary; Using filesort |
| 1 | SIMPLE | pf2 | eq_ref | PRIMARY,feature_id | PRIMARY | 8 | test.person.id,const | 1 | |
| 1 | SIMPLE | pf3 | eq_ref | PRIMARY,feature_id | PRIMARY | 8 | test.person.id,const | 1 | |
| 1 | SIMPLE | pf1 | eq_ref | PRIMARY,feature_id | PRIMARY | 8 | test.person.id,const | 1 | |
+----+-------------+--------+--------+--------------------+---------+---------+----------------------+------+---------------------------------+
我不确定这是否会更快,但您可以尝试使用条件聚合:
select p.name,
max(case when pf.feature_id = 2 then value end) as shyness,
max(case when pf.feature_id = 3 then value end) as kindness,
max(case when pf.feature_id = 1 then value end) as bravery
from person p join
person_features pf
on p.person_id = pf.person_id
group by p.name
order by shyness desc, kindess desc, bravery desc;
另外,在
person\u features(person\u id,feature\u id,value)
上建立一个索引会加快你的查询速度(和这个一样)。不错,这个查询速度快了两倍,但我不确定你是否理解它。为什么要使用MAX函数?顺便说一下,索引对这两个查询没有任何更改。@doskoi。查询正在使用条件聚合来扁平化数据结构。您需要max()
来提取每个特征的值。我很惊讶索引没有帮助。也许您在表定义中已经有了类似的索引。更优雅-但如果它实际上更快(在正确索引的数据集上),我会感到非常惊讶。这是否意味着我的无限关节查询是最优化的p@doskoi-这不是我的专业领域,但我相信是的-尽管你的“统计数据”似乎与我的“信念”相矛盾!!!我们可以看看上面的解释(和正确的DDL)吗
select p.name,
max(case when pf.feature_id = 2 then value end) as shyness,
max(case when pf.feature_id = 3 then value end) as kindness,
max(case when pf.feature_id = 1 then value end) as bravery
from person p join
person_features pf
on p.person_id = pf.person_id
group by p.name
order by shyness desc, kindess desc, bravery desc;