我有一个名为矩阵的表,它包含两列,即cola
和colb
如下所示:
表格:矩阵
create table matrix
(
cola varchar(10),
colb varchar(10)
);
插入行:
insert into matrix values('A1','B1'),('A2','B2'),('A3','B3'),('A4','B4'),
('A5','B5'),('A6','B6'),('A7','B7'),('A8','B8'),
('A9','B9'),('A10','B10'),('A11','B11'),('A12','B12'),
('A13','B13'),('A14','B14'),('A15','B15'),('A16','B16'),
('A17','B17'),('A18','B18'),('A19','B19'),('A20','B20'),
('A21','B21'),('A22','B22'),('A23','B23'),('A24','B24'),
('A25','B25'),('A26','B26'),('A27','B27'),('A28','B28'),
('A29','B29'),('A30','B30');
注意:我想以矩阵的形式显示结果,并计算哪些列属于彼此,并为每列分配矩阵中的值。我刚才 仅举例说明了30条记录,但也可能有数千条记录。所以我需要 为此准备动态数据透视表。预期结果如下所示。
预期结果:
A1 A2 A3 A4 A5 A6 ................ A30
------------------------------------------------------------------
B1 | 1 0 0 0 0 0 0
|
B2 | 0 1 0 0 0 0 0
|
B3 | 0 0 1 0 0 0 0
|
B4 | 0 0 0 1 0 0 0
|
B5 | 0 0 0 0 1 0 0
|
B6 | 0 0 0 0 0 1 0
. |
. |
. |
. |
B30| 0 0 0 0 0 0 1
答案 0 :(得分:2)
您可以使用附加模块tablefunc中的crosstab()
执行此操作:
SELECT b
, COALESCE(a1, 0) AS "A1"
, COALESCE(a2, 0) AS "A2"
, COALESCE(a3, 0) AS "A3"
, ... -- all the way up to "A30"
FROM crosstab(
'SELECT colb, cola, 1 AS val FROM matrix
ORDER BY 1,2'
, $$SELECT 'A'::text || g FROM generate_series(1,30) g$$
) AS t (b text
, a1 int, a2 int, a3 int, a4 int, a5 int, a6 int
, a7 int, a8 int, a9 int, a10 int, a11 int, a12 int
, a13 int, a14 int, a15 int, a16 int, a17 int, a18 int
, a19 int, a20 int, a21 int, a22 int, a23 int, a24 int
, a25 int, a26 int, a27 int, a28 int, a29 int, a30 int);
如果NULL
代替0
,则外部查询中只有SELECT *
。
详细解释:
特殊"难度"这里:没有实际的"价值"。因此,请将1 AS val
添加为最后一列。
单个查询中无法进行完全动态的查询(具有未知结果类型)。您需要两个查询。首先动态构建如上所述的语句,然后执行它。详细说明:
如果超过maximum number of columns (1600),则无法使用经典交叉表,因为结果无法用单个列表示。 (而且,人眼几乎无法读取那么多列的表格)
可以选择hstore
或jsonb
等数组或文档类型。这是一个包含数组的解决方案:
SELECT colb, array_agg(cola) AS colas
FROM (
SELECT colb, right(colb, -1)::int AS sortb
, CASE WHEN m.cola IS NULL THEN 0 ELSE 1 END AS cola
FROM (SELECT DISTINCT colb FROM matrix) b
CROSS JOIN (SELECT DISTINCT cola FROM matrix) a
LEFT JOIN matrix m USING (colb, cola)
ORDER BY sortb, right(cola, -1)::int
) sub
GROUP BY 1, sortb
ORDER BY sortb;
使用以下内容构建完整的值网格:
(SELECT DISTINCT colb FROM matrix) b
CROSS JOIN (SELECT DISTINCT cola FROM matrix) a
LEFT JOIN
现有组合,按名称的数字部分排序并汇总到数组中。
right(colb, -1)::int
修剪了' A3'中的主角。并将数字转换为整数,以便我们得到正确的排序顺序。如果您只想要一张0
和1
x = y
的表格,那么这可能会更便宜:
SELECT x, array_agg((x = y)::int) AS y_arr
FROM generate_series(1,10) x
, generate_series(1,10) y
GROUP BY 1
ORDER BY 1;
SQL Fiddle建立在您在评论中提供的那个。
请注意,sqlfiddle.com目前有一个可以杀死数组值显示的错误。所以我转向text
那里解决它。