Select 多行值到单行与 multi-table 子句
Select multiple row values into single row with multi-table clauses
我搜索了论坛,虽然我看到了类似的帖子,但它们只解决了我需要制定的完整查询的部分(array_aggr、存在位置、连接等)。如果我发布的问题得到解答,我将很乐意接受对这些主题的引用。
我确实找到了 this thread ...这与我需要的非常相似,除了它是针对 MySQL 的,而且我一直在 运行 中尝试将其放入错误中psql 语法。希望有人能帮助我把所有东西放在一起。场景如下:
属性
attrib_id | attrib_name
用户属性
user_id | attrib_id | value
这是数据的一个小例子:
属性
attrib_id | attrib_name
-----------------------
1 | attrib1
2 | attrib2
3 | attrib3
4 | attrib4
5 | attrib5
UserAttribute -- 每个 user_id
最多可以有 15 个 attrib_id's/value
user_id | attrib_id | value
----------------------------
101 | 1 | valueA
101 | 2 | valueB
102 | 1 | valueC
102 | 2 | valueD
103 | 1 | valueA
103 | 2 | valueB
104 | 1 | valueC
104 | 2 | valueD
105 | 1 | valueA
105 | 2 | valueB
这就是我要找的东西
结果
user_id | attrib1_value | attrib2_value
--------------------------------------------------------
101 | valueA | valueB
102 | valueC | valueD
103 | valueA | valueB
104 | valueC | valueD
105 | valueA | valueB
如图所示,我正在寻找包含以下内容的单行:
- user_id 来自 UserAttribute table
- 来自 UserAttribute table
的属性值
注意:对于属性 table
中的两个特定属性名称,我只需要来自 UserAttribute table 的属性值
再次感谢任何帮助或对现有解决方案的参考。
更新:
@ronin 提供了一个获得所需结果的查询:
SELECT ua.user_id
,MAX(CASE WHEN a.attrib_name = 'attrib1' THEN ua.value ELSE NULL END) AS attrib_1_val
,MAX(CASE WHEN a.attrib_name = 'attrib2' THEN ua.value ELSE NULL END) AS attrib_2_val
FROM UserAttribute ua
JOIN Attribute a ON (a.attrib_id = ua.attrib_id)
WHERE a.attrib_name IN ('attrib1', 'attrib2')
GROUP BY ua.user_id;
在此基础上,我尝试在 'WHEN' 条件(针对 ua.value)中添加一些 'LIKE' 模式匹配,但一切都以 'FALSE' 价值。如果我无法弄清楚,将开始一个新问题,看看是否可以合并。感谢大家的帮助!!
如果每个属性对于用户只有一个值,您可以从制作稀疏矩阵开始:
SELECT user_id
,CASE WHEN attrib_id = 1 THEN value ELSE NULL END AS attrib_1_val
,CASE WHEN attrib_id = 2 THEN value ELSE NULL END AS attrib_2_val
FROM UserAttribute;
然后使用聚合函数压缩矩阵:
SELECT user_id
,MAX(CASE WHEN attrib_id = 1 THEN value ELSE NULL END) AS attrib_1_val
,MAX(CASE WHEN attrib_id = 2 THEN value ELSE NULL END) AS attrib_2_val
FROM UserAttribute
GROUP BY user_id;
回复评论,按属性名称而不是id搜索:
SELECT ua.user_id
,MAX(CASE WHEN a.attrib_name = 'attrib1' THEN ua.value ELSE NULL END) AS attrib_1_val
,MAX(CASE WHEN a.attrib_name = 'attrib2' THEN ua.value ELSE NULL END) AS attrib_2_val
FROM UserAttribute ua
JOIN Attribute a ON (a.attrib_id = ua.attrib_id)
WHERE a.attrib_name IN ('attrib1', 'attrib2')
GROUP BY ua.user_id;
像这样的事情怎么样:
select ua.user_id, a.attrib_name attrib_value1, a2.attrib_name attrib_value2
from user_attribute ua
left join attribute a on a.atribute_id=ua.attribute_id and a.attribute_id in (1,2)
left join user_attribute ua2 on ua2.user_id=ua.user_id and ua2.attribute_id > ua.attribute_id
left join attribute a2 on a2.attribute_id=ua2.attribute_id and a2.attribute_id in (1,2)
从 Postgres 9.4 开始,您可以使用更简单的 aggregate FILTER
clause:
SELECT user_id
,MAX(value) FILTER (WHERE attrib_id = 1) AS attrib_1_val
,MAX(value) FILTER (WHERE attrib_id = 2) AS attrib_2_val
FROM UserAttribute
WHERE attrib_id IN (1,2)
GROUP BY 1;
要获得更多属性或最佳性能,请查看附加模块 tablefunc
(Postgres 8.3+) 中的 crosstab()
。详情在这里:
- PostgreSQL Crosstab Query
我搜索了论坛,虽然我看到了类似的帖子,但它们只解决了我需要制定的完整查询的部分(array_aggr、存在位置、连接等)。如果我发布的问题得到解答,我将很乐意接受对这些主题的引用。
我确实找到了 this thread ...这与我需要的非常相似,除了它是针对 MySQL 的,而且我一直在 运行 中尝试将其放入错误中psql 语法。希望有人能帮助我把所有东西放在一起。场景如下:
属性
attrib_id | attrib_name
用户属性
user_id | attrib_id | value
这是数据的一个小例子:
属性
attrib_id | attrib_name
-----------------------
1 | attrib1
2 | attrib2
3 | attrib3
4 | attrib4
5 | attrib5
UserAttribute -- 每个 user_id
最多可以有 15 个 attrib_id's/valueuser_id | attrib_id | value
----------------------------
101 | 1 | valueA
101 | 2 | valueB
102 | 1 | valueC
102 | 2 | valueD
103 | 1 | valueA
103 | 2 | valueB
104 | 1 | valueC
104 | 2 | valueD
105 | 1 | valueA
105 | 2 | valueB
这就是我要找的东西
结果
user_id | attrib1_value | attrib2_value
--------------------------------------------------------
101 | valueA | valueB
102 | valueC | valueD
103 | valueA | valueB
104 | valueC | valueD
105 | valueA | valueB
如图所示,我正在寻找包含以下内容的单行: - user_id 来自 UserAttribute table - 来自 UserAttribute table
的属性值注意:对于属性 table
中的两个特定属性名称,我只需要来自 UserAttribute table 的属性值再次感谢任何帮助或对现有解决方案的参考。
更新:
@ronin 提供了一个获得所需结果的查询:
SELECT ua.user_id
,MAX(CASE WHEN a.attrib_name = 'attrib1' THEN ua.value ELSE NULL END) AS attrib_1_val
,MAX(CASE WHEN a.attrib_name = 'attrib2' THEN ua.value ELSE NULL END) AS attrib_2_val
FROM UserAttribute ua
JOIN Attribute a ON (a.attrib_id = ua.attrib_id)
WHERE a.attrib_name IN ('attrib1', 'attrib2')
GROUP BY ua.user_id;
在此基础上,我尝试在 'WHEN' 条件(针对 ua.value)中添加一些 'LIKE' 模式匹配,但一切都以 'FALSE' 价值。如果我无法弄清楚,将开始一个新问题,看看是否可以合并。感谢大家的帮助!!
如果每个属性对于用户只有一个值,您可以从制作稀疏矩阵开始:
SELECT user_id
,CASE WHEN attrib_id = 1 THEN value ELSE NULL END AS attrib_1_val
,CASE WHEN attrib_id = 2 THEN value ELSE NULL END AS attrib_2_val
FROM UserAttribute;
然后使用聚合函数压缩矩阵:
SELECT user_id
,MAX(CASE WHEN attrib_id = 1 THEN value ELSE NULL END) AS attrib_1_val
,MAX(CASE WHEN attrib_id = 2 THEN value ELSE NULL END) AS attrib_2_val
FROM UserAttribute
GROUP BY user_id;
回复评论,按属性名称而不是id搜索:
SELECT ua.user_id
,MAX(CASE WHEN a.attrib_name = 'attrib1' THEN ua.value ELSE NULL END) AS attrib_1_val
,MAX(CASE WHEN a.attrib_name = 'attrib2' THEN ua.value ELSE NULL END) AS attrib_2_val
FROM UserAttribute ua
JOIN Attribute a ON (a.attrib_id = ua.attrib_id)
WHERE a.attrib_name IN ('attrib1', 'attrib2')
GROUP BY ua.user_id;
像这样的事情怎么样:
select ua.user_id, a.attrib_name attrib_value1, a2.attrib_name attrib_value2
from user_attribute ua
left join attribute a on a.atribute_id=ua.attribute_id and a.attribute_id in (1,2)
left join user_attribute ua2 on ua2.user_id=ua.user_id and ua2.attribute_id > ua.attribute_id
left join attribute a2 on a2.attribute_id=ua2.attribute_id and a2.attribute_id in (1,2)
从 Postgres 9.4 开始,您可以使用更简单的 aggregate FILTER
clause:
SELECT user_id
,MAX(value) FILTER (WHERE attrib_id = 1) AS attrib_1_val
,MAX(value) FILTER (WHERE attrib_id = 2) AS attrib_2_val
FROM UserAttribute
WHERE attrib_id IN (1,2)
GROUP BY 1;
要获得更多属性或最佳性能,请查看附加模块 tablefunc
(Postgres 8.3+) 中的 crosstab()
。详情在这里:
- PostgreSQL Crosstab Query