【问题标题】:Right mySql command to get meta information?对mySql命令获取元信息?
【发布时间】:2011-09-29 22:54:27
【问题描述】:

Wordpress 是一个很好的 Web 应用程序示例,它使用一个表来存储用户信息,然后使用元查找表来存储用户数据。唯一的问题是,我知道获取用户列表的完整元信息列表的唯一方法是“手动”构建 sql 语句 - 硬编码或在 PHP 的帮助下。

用户表如下所示:

wp_users 表

ID|user_login|user_email|user_pass|date_registered ==================================================== 1|我 |me@me1.com|f239j283r| 2011-01-01

wp_usermeta 表

umeta_id|user_id|meta_key|meta_value ===================================== 1 | 1 |电话 | 123-4567 1 | 1 |名称 |约翰 1 | 1 |姓名 |母鹿

我知道我可以做这样的事情(手动或使用 php)来实现我想要的结果:

选择 * 来自 wp_users 左加入 wp_usermeta 作为电话 (ID = user_id) AND (meta_key = phone) left join wp_usermeta as fname on (ID = user_id) AND (meta_key = fname) left join wp_usermeta as lname on (ID = user_id) AND (meta_key = lname)

产生类似这样的东西:

ID|user_login|user_email|user_pass|date_registered|电话|fname|lname ==================================================== ================+++=== 1|我 |me@me1.com|f239j283r| 2011-01-01 |123-4567|约翰|能源部

我知道 mySql 也有 GROUP_CONCAT 的东西,这就是为什么我觉得有更好的方法。看起来像这样:

选择 *, group_concat(meta_value) 作为 all_meta 来自 wp_users 在 ID = user_id 上左加入 wp_usermeta 按 wp_users.ID 分组

那么有没有办法通过像第二个更动态的 sql 语句来获得类似于第一个 sql 语句的结果?

编辑

Doug 提出了一个有趣的解决方案,可能使用 information_schema。我无法让它工作,所以我为任何想要测试他们的 SQL 的人发布了两个表的转储:) http://pastebin.com/w0jkxnws

【问题讨论】:

  • 我不清楚您的目标,基于所列答案的 cmets。 Andriy M 的解决方案是 elagent,但需要知道列名。正如您所建议的,使用 group_concat 可以动态获取所有信息。没有真正的方法可以动态翻转桌子(AFAIK),所以你已经列出了几乎所有的选项。
  • 我在陈述我的目标时尽量简洁明了。归根结底,元查找表是包含用户列表(或其他项目)抽象信息的最具可扩展性的方式;然而,以表格格式为用户获取所有数据似乎需要很多步骤。在研究它之后我已经放弃了它,但我一直看到在 SO 上做事的非常聪明的方式(比如stackoverflow.com/questions/9122)所以我发布了这个问题,希望有一种比硬编码更动态的方式,或者使用PHP 和多个查询。也许没有
  • 啊。引用的答案会起作用,但是从 information_schema 中提取每个查询确实会产生高昂的间接费用。我建议在代码中执行此操作,并缓存结果(这样您就不必一直重新执行此操作),但我很乐意给出这样的答案。
  • 我不同意使用 information_schema 必然会产生“高昂的间接费用”——我们可以运行查询分析来找出答案。我欢迎使用 information_schema 来达到预期结果的答案。与已经发布的答案相比,这更像是我希望的方向(我已经知道这些方法)。谢谢道格!
  • 这当然取决于你在做什么,任务有多复杂,你的模式有多复杂。计数很糟糕,但在我的大型数据库中,运行 select count(*) from information_schema.columns; 需要 7.6 秒来处理 15,000 条记录。

标签: php mysql sql


【解决方案1】:

这就是你要找的吗?还是3个语句,不过和我之前的语句相反,应该不会有太多的准备成本。

set group_concat_max_len = 2048;
SELECT CONCAT('SELECT u.id, u.user_login, ', GROUP_CONCAT(concat('
    (SELECT meta_value FROM wp_usermeta WHERE user_id = u.id AND meta_key = "', um.meta_key, '") `', um.meta_key, '`') SEPARATOR ", "), '
    FROM wp_users u ') FROM (SELECT DISTINCT meta_key FROM wp_usermeta) um INTO @sql;

PREPARE stmt1 FROM @sql;
EXECUTE stmt1;

【讨论】:

  • 谢谢,Doug,它看起来很有趣,但对我来说没有运气。我在您的查询中间收到与 user_id = u.id 相关的错误,我似乎无法解决它。你测试过这个sql语句吗?以下是您可以使用的两个表格和数据:pastebin.com/w0jkxnws
  • 我测试了它,但只测试了 3 个字段。它正在被截断 - 我正在研究解决方案......
  • set group_concat_max_len = 2048;(添加在答案中)解决了您的数据集的问题。
  • 这看起来太棒了!我印象深刻!在更大的桌子上,我不得不提高 max_len,但这对我来说没问题。不过,它可能仍需要再进行一次调整。它正在创建重复的列,可能基于用户数量:img696.imageshack.us/img696/3893/picturelu.png - 似乎我们需要在 WHERE 子句中再添加一个条件?
  • 我刚刚在语句末尾添加了“选择不同的”子查询 - 这应该可以解决它。
【解决方案2】:

这通常是通过对数据库运行 2 个查询来完成的 - 第一个是获取用户记录,第二个是属性。

【讨论】:

  • 是的,我认为这就是我用 php 手动构建 sql 语句的意思。谢谢:)
【解决方案3】:

试试这个

select *
from wp_users
left join wp_usermeta as fname on (ID = user_id)
where meta_key in ('fname','lname','phone')
group by ID, meta_key;

【讨论】:

  • 谢谢。查询“有效”,但它为每个用户生成多行。我的目标是每个用户有一行,所有元数据都在它自己的列中。
  • 然后您可以将GROUP_CONCAT(meta_value) 添加到您的选择中并从group by 中删除meta_key。如果您希望所有内容都在一个列中。
  • 是的,这是我在问题中提供的第二个查询示例。谢谢。
  • 所以你想要的不是所有元数据都在它自己的列中,而是每条元数据都在它自己的列中。您可以使用子查询来实现这一点,但如果可能,如果您不喜欢现有查询的外观,最好修改您的应用程序逻辑。
【解决方案4】:

你可以试试这样的:

SELECT
  u.*,
  MIN(CASE m.meta_key WHEN 'phone' THEN m.meta_value END) AS phone,
  MIN(CASE m.meta_key WHEN 'fname' THEN m.meta_value END) AS fname,
  MIN(CASE m.meta_key WHEN 'lname' THEN m.meta_value END) AS lname
FROM wp_users u
  LEFT JOIN wp_usermeta m ON u.ID = m.user_id
    AND m.meta_key IN ('phone', 'fname', 'lname')
GROUP BY u.ID

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-22
    相关资源
    最近更新 更多