1

我搜索了论坛,虽然我看到了类似的帖子,但它们只解决了我需要制定的完整查询的部分内容(array_aggr、存在的位置、连接等)。如果我发布的问题已得到解答,我将很乐意接受对这些主题的引用。

我确实找到了这个线程......这与我需要的非常相似,除了它是用于 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's

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

如图所示,我正在寻找包含以下内容的单行: - UserAttribute 表中的 user_id - UserAttribute 表中的属性值

注意:对于 Attribute 表中的两个特定属性名称,我只需要 UserAttribute 表中的属性值

同样,我们将不胜感激任何对现有解决方案的帮助或参考。


更新:

@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' 值结束。如果我无法弄清楚,将开始一个新问题,看看是否可以合并。谢谢大家的帮助!!

4

3 回答 3

3

如果每个属性对于一个用户只有一个值,你可以从创建一个稀疏矩阵开始:

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;
于 2015-02-11T00:44:44.633 回答
1

从 Postgres 9.4开始,您可以使用更简单的聚合FILTER子句

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;

要获得更多属性或最佳性能,请查看crosstab()附加模块tablefunc(Postgres 8.3+)。详情在这里:

于 2015-02-11T12:47:18.873 回答
0

像这样的东西怎么样:

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)
于 2015-02-11T04:59:00.993 回答