如何根据连接表值选择“假”列/值?
Posted
技术标签:
【中文标题】如何根据连接表值选择“假”列/值?【英文标题】:How do I SELECT a "fake" column/value based on joined table values? 【发布时间】:2013-08-08 00:17:11 【问题描述】:短版:
我需要自定义查询结果,使用一个值作为列名,另一个值作为列的值。它还需要是自动的(不是硬编码,数百个可能的“元键”)。
加长版:
我正在使用 Wordpress 的“用户元”结构,其中单个用户有一个用户 ID,另一个表包含与该用户相关的“元数据”。
这个元数据是任意的,只有四列:
meta_id
、post_id
、meta_key
、meta_value
。
我想为某个用户执行 SQL 查询,并格式化结果,以便所有元数据都像行一样被格式化,其中 meta_key
是列名,meta_value
是列的值。
示例数据库:
-- wp_users
* ID | username | email
35 | radgh | radgh@example.org
-- wp_usermeta
* meta_id | user_id | meta_key | meta_value
1 | 35 | first-name | Radley
2 | 35 | last-name | Sustaire
3 | 35 | newsletter | on
我的查询(我需要弄清楚 (???) 部分,它将生成元键/值对作为假列)
SELECT
`users`.ID as 'user_id',
`users`.username as 'username',
`users`.email as 'email',
(???)
FROM `wp_users` `users`
INNER JOIN `wp_usermeta` `meta`
ON `users`.ID = `meta`.user_id
WHERE `wp_users`.ID = 35
期望的结果:
* user_id | username | email | first-name | last-name | newsletter
35 | radgh | radgh@example.org | Radley | Sustaire | on
在这个similar question 中,所选答案使用硬编码字段。我想自动执行此操作。 :)
【问题讨论】:
采用“myfakecolumn”并尝试应用此逻辑。 [***.com/questions/15091330/…[1]:***.com/questions/15091330/… 【参考方案1】:它被称为Entity–attribute–value model。 mysql 中通过简单/复杂查询的动态列(元数据)的解决方案是 AFAIK 无法实现的(就像缺少 PIVOT
MySQL 等其他强大功能一样)。我认为唯一的方法是静态定义或MySQL function,它从元表中获取可能的属性并构建正确的查询。
请看What is best performance for Retrieving MySQL EAV results as Relational Table
还可以阅读堆栈上的 EAV 设计(优点/缺点)Entity-Attribute-Value Table Design
【讨论】:
这么多行话要学,难怪我在寻找类似问题时遇到这么多麻烦!我会研究一下这个,谢谢!由于这可能是不可能的,也许做一个单独的查询只是为了找到每个元键,然后使用 php 将其格式化为“硬编码”布局。【参考方案2】:MySQL 没有枢轴功能。如果您已经知道 meta_key 的所有可能值,则可以使用这样的硬编码查询:
SELECT
wp_users.*,
MAX(CASE WHEN `meta_key`='first-name' THEN meta_value END) AS `first-name`,
MAX(CASE WHEN `meta_key`='last-name' THEN meta_value END) AS `last-name`,
....
FROM
wp_users INNER JOIN wp_usermeta
ON wp_users.ID=wp_usermeta.user_id
GROUP BY
wp_users.ID, wp_users.username, wp_users.email;
或者您可以使用准备好的语句动态创建 SQL 查询,如下所示:
SELECT
CONCAT(
'SELECT wp_users.*,',
GROUP_CONCAT(
CONCAT(
'MAX(CASE WHEN `meta_key`=\'',
meta_key,
'\' THEN meta_value END) AS `',
meta_key,
'`')),
' FROM wp_users INNER JOIN wp_usermeta ON wp_users.ID=wp_usermeta.user_id',
' GROUP BY wp_users.ID, wp_users.username, wp_users.email')
FROM
(SELECT DISTINCT meta_key FROM wp_usermeta) s
INTO @sql;
PREPARE stmt FROM @sql;
EXECUTE stmt;
请看小提琴here。
【讨论】:
我想了想,可以使用两个查询,一个收集所有可能的元键,然后使用 PHP 构建第二个查询,如示例 #1。但是,我刚刚使用 #2 并创建了一个新行,它似乎就像我想开始的那样工作。虽然有点难读;)。选项#1 与#2 相比会有很大的好处吗?我怀疑 #2 会进行许多 SELECT 查询,但这里不需要性能 - 这个脚本不会经常使用。 我无法在 MySQL 5.1.54 上获得第二个选项来使用 HeidiSQL(不是应用程序很重要)。不过,无需调试它,因为我最终选择了选项#1,使用了我上次评论中的想法。事实上,存储这些字段的插件(用于 wordpress)有一个包含所有字段名称的全局变量,所以最后我什至不需要额外的查询,也不必担心所有不必要的字段 -只有当前可用的。最后,我认为无论如何这是最好的选择。感谢您提供示例查询!以上是关于如何根据连接表值选择“假”列/值?的主要内容,如果未能解决你的问题,请参考以下文章