我有一个名为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个属性。是否有可能实现自动化?
答案 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)