我有这些表:
Objects
ID | Name
----------
1 name1
Tags
ID | ObjectId | Tag
--------------------
1 1 tag1
2 1 tag2
Attributes
ID | ObjectId | Key | Value
--------------------
1 1 key1 value1
2 1 key2 value2
我想检索这些值并将它们映射到我的应用程序代码中的单个对象中。像这样:
id: 1,
name: name1,
tags: [tag=tag1, tag=tag2],
attributes: [{key=key1, value=value1}, {key=key2, value=value2}]
但是,此联接查询无法按我的预期工作:
SELECT o.id, o.name, t.tag, a.key, a.value
FROM objects o
LEFT JOIN attributes a on a.ObjectId = o.id
LEFT JOIN tags t on t.ObjectId = o.id
WHERE o.id = 1
它给了我这4个结果:
1 | key1 | value1 | tag1
1 | key2 | value2 | tag1
1 | key1 | value1 | tag2
1 | key2 | value2 | tag2
这让我感到惊讶,因为我期望null
的一半Attribute
和一半Tags
的结果。
当我在应用程序代码中映射它时,由于没有办法知道tag1
之类的事物是否应该发生多次,所以最终得到重复的值。
我应该如何查询这些数据,以便可以在应用程序代码中映射到这样的对象?
答案 0 :(得分:1)
您可以使用GROUP_CONCAT()
获得所需的内容。使用DISTINCT
修饰符删除重复项。
SELECT o.id, o.name,
GROUP_CONCAT(DISTINCT t.tag) AS tags,
GROUP_CONCAT(DISTINCT CONCAT(a.key, '=', a.value)) AS attributes
FROM object AS o
LEFT JOIN attributes a on a.ObjectId = o.id
LEFT JOIN tags t on t.ObjectId = o.id
WHERE o.id = 1
然后您可以在应用程序语言中拆分这些逗号分隔和相等分隔的字符串。
或者您可以使用现有查询,并以应用程序语言合并相关行。
如果输入表中存在重复项,如果您需要结果包含重复项,请与使用GROUP_CONCAT
的子查询一起加入:
SELECT o.id, o.name, t.tags, a.attributes
FROM object AS o
LEFT JOIN (
SELECT ObjectId, GROUP_CONCAT(key, '-', value) AS attributes
FROM attributes
GROUP BY ObjectId
) AS a ON a.ObjectId = o.id
LEFT JOIN (
SELECT ObjectId, GROUP_CONCAT(tag) AS tags
FROM tags
GROUP BY OBjectId
) AS t ON a.ObjectId = t.id
WHERE o.id = 1
答案 1 :(得分:0)
MySQL 8及更高版本具有本机JSON支持,因此您可以执行以下操作:
SELECT o.ID, o.Name, t.tags, a.attributes
FROM Objects o
LEFT JOIN (SELECT ObjectId, JSON_ARRAYAGG(Tag) tags FROM Tags GROUP BY ObjectId) t
ON t.ObjectId = o.ID
LEFT JOIN (SELECT ObjectId, JSON_OBJECTAGG(`Key`, `Value`) attributes FROM Attributes GROUP BY ObjectId) a
ON a.ObjectId = o.ID
WHERE o.ID = 1;
这将导致
| ID | Name | tags | attributes | | --- | ----- | ---------------- | ------------------------------------ | | 1 | name1 | ["tag1", "tag2"] | {"key1": "value1", "key2": "value2"} |