2012-04-03 85 views
0

我发现了postgres的crosstab函数中一个奇怪的行为,我无法解释,但希望其他人可能...为什么空日期导致交叉表功能失败?

我使用的交叉表函数的版本需要先构建一个初步表。

此SQL成功地创建了初步表:

SELECT 
    ST.studyabrv||' '||S.labid||' '||S.subjectid||' '||S.box::varchar||' '||S.well AS "rowname", 
    M.marker AS "bucket", 
    G.allele1||' '||G.allele2 AS "bucket_value" 
INTO TABLE ct 
FROM 
    geno.gmarkers M, 
    geno.genotypes G, 
    geno.gsamples S, 
    geno.guploads U, 
    geno.gibg_studies ST 
WHERE 
    G.markers_id=M.id 
    AND G.gsamples_id=S.id 
    AND S.guploads_id=U.id 
    AND U.ibg_study_id=ST.id 
    AND (M.id=5 OR M.id=6 OR M.id=2 OR M.id=4 OR M.id=3) 
    AND (S.labid='CL100001' OR S.labid='CL100002' OR S.labid='CL100003' OR S.labid='CL100004' OR S.labid='CL100005' OR S.labid='CL100006' OR S.labid='CL100007' OR S.labid='CL100008' OR S.labid='CL100009' OR S.labid='CL100010' OR S.labid='CL100011' OR S.labid='CL100012' OR S.labid='CL100013' OR S.labid='CL100014' OR S.labid='CL100015') 
ORDER BY box,well; 

,类似的产生输出:

  rowname   | bucket | bucket_value 
--------------------------+-----------+-------------- 
LTS CL100001 10011 1 A01 | 5HTTLPR-T | S La 
LTS CL100001 10011 1 A01 | 5HTTLPR-D | 14 16 
LTS CL100001 10011 1 A01 | DAT1  | 440 480 
LTS CL100001 10011 1 A01 | DRD4  | 475 475 
LTS CL100001 10011 1 A01 | Caspi  | 351 351 
LTS CL100009 10420 1 A02 | Caspi  | 
LTS CL100009 10420 1 A02 | 5HTTLPR-T | La Lg 
LTS CL100009 10420 1 A02 | 5HTTLPR-D | 16 16 
LTS CL100009 10420 1 A02 | DAT1  | 440 480 
LTS CL100009 10420 1 A02 | DRD4  | 475 475 
... 

但是,如果我尝试包括日期栏,里面全是空,如下所示:

SELECT 
    ST.studyabrv||' '||S.labid||' '||S.subjectid||' '||S.box::varchar||' '||S.well||' '||G.run_date::text AS "rowname", 
    M.marker AS "bucket", 
    G.allele1||' '||G.allele2 AS "bucket_value" 
INTO TABLE ct 
FROM 
    geno.gmarkers M, 
    geno.genotypes G, 
    geno.gsamples S, 
    geno.guploads U, 
    geno.gibg_studies ST 
WHERE 
    G.markers_id=M.id 
    AND G.gsamples_id=S.id 
    AND S.guploads_id=U.id 
    AND U.ibg_study_id=ST.id 
    AND (M.id=5 OR M.id=6 OR M.id=2 OR M.id=4 OR M.id=3) 
    AND (S.labid='CL100001' OR S.labid='CL100002' OR S.labid='CL100003' OR S.labid='CL100004' OR S.labid='CL100005' OR S.labid='CL100006' OR S.labid='CL100007' OR S.labid='CL100008' OR S.labid='CL100009' OR S.labid='CL100010' OR S.labid='CL100011' OR S.labid='CL100012' OR S.labid='CL100013' OR S.labid='CL100014' OR S.labid='CL100015') 
ORDER BY box,well; 

这产生输出:

rowname | bucket | bucket_value 
---------+-----------+-------------- 
     | 5HTTLPR-T | S La 
     | 5HTTLPR-D | 14 16 
     | DAT1  | 440 480 
     | DRD4  | 475 475 
     | Caspi  | 351 351 
     | Caspi  | 
     | 5HTTLPR-T | La Lg 
     | 5HTTLPR-D | 16 16 

正如你所看到的,将run_date列添加到“rowname”组合列的末尾会呈现整个组合空白......这是疯狂的。 如果我使用虚拟数据填充run_date,它将显示....但是如果它为空或空,这会导致“rowname”变为空白。

我不能说这是否是postgres中的错误,但如果可能的话,这是一个奇怪的结果,我想解决。

TIA, rixter

回答

0

你应该想到的null作为unknown值。 null值不是数字或字符串,所以你不能像对待它们那样对它们进行操作。所以你应该确保你使用了一些会返回非空值的函数,比如coalesce(),它会从左到右返回第一个非空参数,并强制默认值作为最右边的参数。

+0

谢谢!将检查合并功能。 – rixter 2012-04-04 19:26:29

+0

欢迎!只是不要为postgresql提出这样的错误:P – 2012-04-04 19:27:49

+0

这个工作,使用用户同意的虚拟值:|| coalesce(G.run_date,'01/01/1900'):: text – rixter 2012-04-04 19:33:19

0
|| coalesce(G.run_date, '')::text 
+0

谢谢!将检查合并功能。 – rixter 2012-04-04 19:27:51

相关问题