MySQL 查询从另一个表检索相关数据

问题描述 投票:0回答:4

我对 SQL 查询不太有经验(大多数时候我使用框架中的查询生成器,如 CodeIgniter 和 Laravel)。现在,我需要从关系数据库中检索数据,该数据库有两个表:一个用于实体条目,另一个用于实体的补充数据。例如,见下图:

tbl_posts

id 名字 蛞蝓
1 Lorem ipsum lorem-ipsum
2 测试帖 测试帖
3 世界你好 你好世界

tbl_posts_meta

id post_id 价值
1 1 名字 约翰
2 1 姓氏 美国能源部
3 1 评分 5
4 2 家长 1
5 2 评分 3
6 3 评分 4

在此示例中,我需要检索以下格式的对象数组:

[
  {
    id: 1,
    name: "Lorem ipsum",
    slug: "lorem-ipsum",
    data: {
      first_name: "John",
      last_name: "Doe",
      rating: 5,
    }
  },
  {
    id: 2,
    name: "Testing post",
    slug: "testing-post",
    data: {
      parent: 1,
      rating: 3,
    }
  },
  {
    id: 3,
    name: "Hello World",
    slug: "hello-world",
    data: {
      rating: 4,
    }
  },
]

我尝试使用子查询来处理这个问题,但我收到了

Cardinality violation: 1241 Operand should contain 1 column(s)
错误。我的查询如下所示:

SELECT *,(SELECT * FROM tbl_posts_meta WHERE "post_id" = "tbl_posts"."id") as data FROM tbl_posts;

我已经尝试使用 JOIN,但结果看起来与预期相差更大(结果中有一个“键”属性和一个“值”属性,包含 tbl_posts_meta 中最后找到的条目)。

SELECT * FROM tbl_posts INNER JOIN tbl_posts_meta ON tbl_posts_meta.post_id = tbl_posts.id;

有什么办法可以通过一次查询检索所需的结果吗?我不想通过应用程序逻辑来执行此操作(例如首先从 tbl_posts 检索数据并在“data”属性上附加另一个查询,该查询返回来自 tbl_posts_meta 的所有数据),因为这种方式可能会导致数据库过载。

谢谢!

mysql
4个回答
0
投票

代码没有在评论中正确显示,所以这里供您检查,抱歉我无法为理论辩论做出更多贡献:

select 
tp.id,
tp.name,
tp.slug,
(select group_concat(`key`, "=",value separator ';' ) from tbl_posts_meta where post_id= tp.id )as datas
from tbl_posts tp

0
投票

您可以按照以下简单步骤获取所需的 json:

  • 连接两个表以获得集中数据
  • 通过使用
    tbl_posts_meta
    聚合函数聚合您感兴趣的列(
    tbl_posts.id
    tbl_posts.name
    tbl_posts.slug
    )来生成类似 JSON 的字符串。由于您的键可以是整数或字符串,因此您需要使用
    GROUP_CONCAT
    进行快速检查,如果字符串不是数字,它将返回 0。
    使用 
  • CAST(<col> AS UNSIGNED)
  • 函数将每一行转换为 JSON
    使用 
  • JSON_OBJECT
  • 函数将所有 json 合并为一个 json。
    
    
  • JSON_ARRAYAGG
查看演示
这里


0
投票

WITH cte AS( SELECT p.id, p.name, p.slug, CONCAT('{', GROUP_CONCAT( CONCAT('"', m.key_, '": ', IF(CAST(m.value_ AS UNSIGNED)=0, CONCAT('"', m.value_, '"'), CAST(m.value_ AS UNSIGNED)) ) ORDER BY m.id ), '}') AS data_ FROM tbl_posts p INNER JOIN tbl_posts_meta m ON p.id = m.post_id GROUP BY p.id, p.name, p.slug ) SELECT JSON_ARRAYAGG( JSON_OBJECT("id", id, "name", name, "slug", slug, "data", CAST(data_ AS JSON))) FROM cte

将其转换为 Laravel 的 Eloquent 查询构建器,并使用 PHP 的序列化/反序列化函数,最终结果如下所示:

SELECT *, ( SELECT JSON_ARRAYAGG( JSON_OBJECT( key, value ) ) FROM tbl_posts_meta WHERE post_id = post.id ) AS data FROM tbl_posts;

感谢您的支持和关注! :)


0
投票
© www.soinside.com 2019 - 2024. All rights reserved.