I'm not too experienced with SQL queries (most times I used query builder from frameworks, like CodeIgniter and Laravel). Now, I need to retrieve data from a relational DB which have two tables: one for entity entries and other for complemental data of entities. For example, see below:
tbl_posts
| id | name | slug |
| ------------ | ------------ | ------------ |
| 1 | Lorem ipsum | lorem-ipsum |
| 2 | Testing post | testing-post |
| 3 | Hello world | hello-world |
tbl_posts_meta
| id | post_id | key | value |
| ------------ | ------------ | ------------ | ------------ |
| 1 | 1 | first_name | John |
| 2 | 1 | last_name | Doe |
| 3 | 1 | rating | 5 |
| 4 | 2 | parent | 1 |
| 5 | 2 | rating | 3 |
| 6 | 3 | rating | 4 |
In this example, I need to retrieve an array of objects in this format:
[
{
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,
}
},
]
I've tried using subquery to handle this, but I'm reveiving Cardinality violation: 1241 Operand should contain 1 column(s)
error. My query looks like this:
SELECT *,(SELECT * FROM tbl_posts_meta WHERE "post_id" = "tbl_posts"."id") as data FROM tbl_posts;
I've already tried using JOIN, but the result looks more away from expected (I have one "key" property and one "value" property in result, containing the last found entry in tbl_posts_meta).
SELECT * FROM tbl_posts INNER JOIN tbl_posts_meta ON tbl_posts_meta.post_id = tbl_posts.id;
Is there someway I can retrieve desired results with one query? I don't want to do this by applogic (like first retrieving data from tbl_posts and appending another query on "data" property, that returns all data from tbl_posts_meta), since this way may cause database overload.
Thanks!
3条答案
按热度按时间eoigrqb61#
代码没有在注解中显示出来,所以在这里你可以检查一下,对不起,我不能为理论上的争论做出更多的贡献:
6kkfgxo02#
您可以按照以下简单的步骤来获得所需的json:
GROUP_CONCAT
聚合函数聚合您感兴趣的列(tbl_posts.id
、tbl_posts.name
、tbl_posts.slug
),生成一个tbl_posts_meta
类JSON字符串。由于键可以是整数或字符串,因此需要使用CAST(<col> AS UNSIGNED)
进行快速检查,如果字符串不是数字,则返回0。JSON_OBJECT
函数将每行转换为JSONJSON_ARRAYAGG
函数将所有json合并为单个json。检查演示here。
a6b3iqyw3#
经过一些研究、测试和阅读您在此处发布的查询后,我终于得到了我所需要的结果。最终的查询结构如下:
将其转换为Laravel的Eloquent查询构建器,并使用PHP的serialize/unserialize函数,最终结果如下所示:
感谢您的支持和关注!:)