Postgres Crosstab将值分配给错误的列

时间:2017-11-13 20:54:41

标签: postgresql pivot crosstab

我有一个名为antest的示例表,如下所示,用于测试交叉表函数。

create table antest(student text, subject text, result numeric);
insert into antest(student, subject, result) values
('peter','music',2.0), 
('peter','language',2.0),
('gabriel','history',8.0),
('john','history',9.0),
('john','maths',4.0),
('john','music',7.0);

student|subject|result
-------+-------+------
peter  |music  |2.0
peter  |lanuage|2.0
gabriel|history|8.0
john   |history|9.0
john   |maths  |4.0
john   |music  |7.0

想要的结果:

student|music|language|history|maths
-------+-----+--------+-------+-----
peter  |2.0  |2.0     |       |
gabriel|     |        |8.0    |
john   |7.0  |        |9.0    |4.0

我已经执行了以下的查询:

select * from public.crosstab ('select student, subject, result from antest', 'select distinct subject from antest') as final_result(student text, music numeric, maths numeric, history numeric, language numeric);

我得到了以下结果:

student|music|maths|history|language
-------+-----+-----+-------+--------
peter  |2.0  |     |       |2.0
gabriel|     |8.0  |       |
john   |7.0  |9.0  |4.0    |

请让我知道我正在做的错误。

我必须为之后30gb大的任何其他数据库重复此查询,其中包含大约75个属性。是否有可能实现自动化?

1 个答案:

答案 0 :(得分:1)

您必须注意类别查询和列定义中类别的顺序完全相同。因为您需要任意选择(非按字母顺序)的顺序,所以您应该在类别查询中使用mapMaybe :: (a -> Maybe b) -> [a] -> [b]

import Data.Maybe (catMaybes)

charVal :: Char -> Maybe Int
charVal 'A' = Just 1
charVal 'B' = Just 2
charVal 'C' = Just 3
charVal _   = Nothing

checkIfTrue :: String -> Int -> Bool
checkIfTrue s k = k == stringSum where
  stringSum = sum . (mapMaybe charVal) $ s

当然,您可以在查询中使用values,但是您必须更改列定义中的顺序:

select * 
from crosstab (
    $q$ select student, subject, result from antest $q$,
    $q$ values ('music'), ('language'), ('history'), ('maths') $q$
) as final_result(student text, music numeric, language numeric, history numeric, maths numeric);


 student | music | language | history | maths 
---------+-------+----------+---------+-------
 peter   |   2.0 |      2.0 |         |      
 gabriel |       |          |     8.0 |      
 john    |   7.0 |          |     9.0 |   4.0
(3 rows)