我对 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 的所有数据),因为这种方式可能会导致数据库过载。
谢谢!
代码没有在评论中正确显示,所以这里供您检查,抱歉我无法为理论辩论做出更多贡献:
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
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;
感谢您的支持和关注! :)