3

我有实验、特性和特性值。特征在不同的实验中具有价值。所以我有类似的东西:

Experiments:
experiment_id, experiment_name

Features:
feature_id, feature_name

Feature_values:
experiment_id, feature_id, value

可以说,我有三个实验(exp1、exp2、exp3)和三个特征(feat1、feat2、feat3)。我想要一个如下所示的 SQL 结果:

feature_name | exp1 | exp2 | exp3
-------------+------+------+-----
feat1        | 100  | 150  | 110
feat2        | 200  | 250  | 210
feat3        | 300  | 350  | 310

我怎样才能做到这一点?此外,一个特征可能在一个实验中没有价值。

feature_name | exp1 | exp2 | exp3
-------------+------+------+-----
feat1        | 100  | 150  | 110
feat2        | 200  |      | 210
feat3        |      | 350  | 310

SQL-Query 应该具有良好的性能。将来,feature_values 表中可能会有数千万个条目。还是有更好的方法来处理数据?

4

3 回答 3

5

这是一个常见的要求。这称为数据透视表或交叉表查询。PostgreSQL 没有任何好的内置语法,但你可以使用模块中crosstab函数tablefunc来做你想做的事

有关更多信息,请搜索 Stack Overflow[postgresql] [pivot][postgresql] [crosstab]

一些关系数据库系统提供了一种很好的方法来使用内置查询来做到这一点,但目前 PostgreSQL 还没有。

于 2013-08-27T11:28:52.247 回答
3

我在这里假设这feature_id, experiment_idFeature_values.

执行此操作的标准 SQL 方法是进行 n 个连接

select
    F.feature_name,
    FV1.value as exp1,
    FV2.value as exp2,
    FV3.value as exp3
from Features as F
    left outer join Feature_values as FV1 on FV1.feature_id = F.feature_id and FV1.experiment_id = 1
    left outer join Feature_values as FV2 on FV2.feature_id = F.feature_id and FV2.experiment_id = 2
    left outer join Feature_values as FV3 on FV3.feature_id = F.feature_id and FV3.experiment_id = 3

或者像这样的数据透视(聚合max实际上并不聚合任何东西):

select
    F.feature_name,
    max(case when E.experiment_name = 'exp1' then FV.value end) as exp1,
    max(case when E.experiment_name = 'exp2' then FV.value end) as exp2,
    max(case when E.experiment_name = 'exp3' then FV.value end) as exp3
from Features as F
    left outer join Feature_values as FV on FV.feature_id = F.feature_id
    left outer join Experiments as E on E.experiment_id = FV.experiment_id
group by F.feature_name
order by F.feature_name

sql fiddle demo

您还可以考虑使用json(在 9.3 版本中)或hstore将所有实验值放入一列。

于 2013-08-27T11:12:23.857 回答
2

您尝试的有点困难,因为您试图将一组表呈现为单个表,显然,这涉及一些转换和一些假设。

假设您事先知道只有 3 个实验和三个功能,您可以执行以下操作

SELECT
    feature_id,
    SUM(CASE WHEN experiment_id = 1 THEN value ELSE 0 END) AS Exp1Total,
    SUM(CASE WHEN experiment_id = 2 THEN value ELSE 0 END) AS Exp2Total,
    SUM(CASE WHEN experiment_id = 3 THEN value ELSE 0 END) AS Exp3Total,
FROM
    Feature_values
GROUP BY
    feature_id
ORDER BY
    feature_id

在这种情况下,您的表格将包含实验的 ID 和特征,而不是它们的名称。要获得他们的名字,您需要加入 Features 表和 Experiments 表。为了清楚起见,我省略了这一点,因为我认为最困难的部分是案例逻辑。

于 2013-08-27T11:20:11.617 回答