选择属性表作为列

时间:2014-07-25 00:03:19

标签: sql postgresql pivot crosstab

我有两个表,thingsproperties

CREATE TABLE things (
  id SERIAL PRIMARY KEY
);

CREATE TABLE properties (
  thing_id INT,
  key TEXT,
  value TEXT
);

我想从things中选择并加入properties中的行作为列。例如,假设我有以下内容:

INSERT INTO things DEFAULT_VALUES;  -- suppose id is 1
INSERT INTO properties (thing_id, key, value) VALUES
  (1, 'height', '5'),
  (1, 'width', '6'),
  (1, 'length', '7');

如何选择heightwidthlength作为列的内容?

此外,我不希望具体选择heightwidthlength,但是可能在属性中的所有行。

2 个答案:

答案 0 :(得分:2)

只有三列:

SELECT t.thing_id
      ,max(CASE WHEN p.key = 'height' THEN p.value END) AS height
      ,max(CASE WHEN p.key = 'width'  THEN p.value END) AS width
      ,max(CASE WHEN p.key = 'length' THEN p.value END) AS length
FROM   things t
LEFT   JOIN properties p ON p.thing_id = t.id
WHERE  t.id = 1
GROUP  BY 1;

或者使用附加模块crosstab()中的tablefunc,这通常更快,而且对于长属性列表更短:

SELECT * FROM crosstab(
      'SELECT t.thing_id, p.key, p.value
       FROM   things t
       LEFT   JOIN properties p ON p.thing_id = t.id
       WHERE  t.id = 1
       ORDER  BY 1'

      ,$$VALUES ('height'::text), ('width'), ('length')$$) -- add more
AS ct (thing_id int, height int, width int, length int);   -- add more

类型必须匹配。详细解释:

在单个查询中无法实现完全动态列列表。我已多次尝试过。以下是可以完成的事情:

答案 1 :(得分:0)

可能你可以在这里尝试表别名:

SELECT  p1.key, p2.key, p3.key
  FROM properties as t1
  JOIN properties AS p1 ON p1.thing_id= t1.thing_id
  JOIN properties AS p2 ON p2.thing_id= t1.thing_id
  JOIN properties AS p3 ON p3.thing_id= t1.thing_id
 WHERE t1.thing_id = 1;