【问题标题】:Multiple sum/counts across multiple tables in PostgreSQLPostgreSQL中多个表的多个总和/计数
【发布时间】:2011-10-14 13:25:04
【问题描述】:

我在这个网站上搜索了几个建议,但还没有完全得到我想要的。我怀疑只是缺少一个语法/标点符号问题。

我使用 phpPgAdmin 在数据库上工作,该数据库跟踪与正在研究的狒狒种群相关的大量信息。我正在尝试进行查询以识别,对于每只狒狒,我们为它们收集了多少不同类型的组织样本,以及我们为每个狒狒收集了多少不同类型的 DNA 样本。有三个表与我的问题:

表:“传记”包含关于该组中所有动物的基本信息,尽管我只关心名称。

name | birth
-----+-----------
A21  | 1968-07-01
AAR  | 2002-03-30
ABB  | 1998-09-10
ABD  | 2005-03-15
ABE  | 1986-01-01

表:“babtissue”跟踪关于多年来收集的不同组织的信息,包括以下三列。此表中的某些行代表我们不再拥有的组织样本,但仍会在数据库的其他地方引用,因此“可用”列帮助我们筛选我们仍然拥有的样本。

name | sample_type | avail
-----+-------------+------
A21  | BLOOD       | Y
A21  | BLOOD       | Y
A21  | TISSUE      | N
ABB  | BLOOD       | Y
ABB  | TISSUE      | Y

表:“dna”类似于 babtissue。

name | sample_type | avail
-----+-------------+------
ABB  | GDNA        | N
ABB  | WGA         | Y
ACC  | WGA         | N
ALE  | GDNA        | Y
ALE  | GDNA        | Y

总而言之,我正在尝试编写一个查询,该查询将返回传记中的每个名字,并在一列中告诉我每个人有多少“BLOOD”、“TISSUE”、“GDNA”和“WGA”样本.有点像...

name | bloodsamps | tissuesamps | gdnas | wgas | avail
-----+------------+-------------+-------+------+------
A21  | 2          | 0           | 0     | 0    | ?
AAR  | 0          | 0           | 0     | 0    | ?
ABB  | 1          | 1           | 0     | 1    | ?
ACC  | 0          | 0           | 0     | 0    | ?
ALE  | 0          | 0           | 2     | 0    | ?

(对上面奇怪的格式表示歉意,我不太熟悉这种方式)

我尝试过的查询的最新版本:

select b.name,  
sum(case when t.sample_type='BLOOD' and t.avail='Y' then 1 else 0 end) as bloodsamps,   
sum(case when t.sample_type='TISSUE' and t.avail='Y' then 1 else 0 end) as tissuesamps,   
sum(case when d.sample_type='GDNA' and d.avail='Y' then 1 else 0 end) as gdnas,  
sum(case when d.sample_type='WGA' and d.avail='Y' then 1 else 0 end) as wgas  
from biograph b  
left join babtissue t on b.name=t.name  
left join dna d on b.name=d.name  
where b.name is not NULL  
group by b.name  
order by b.name  

这样做时我没有收到任何错误,但我知道它给我的数字是错误的——太高了。我认为这与我使用多个连接有关,并且我的连接语法需要更改。

有什么想法吗?

【问题讨论】:

  • 我整理了你的格式,但我不确定你在avail 列中想要什么,所以我把? 留在那里。
  • 谢谢,@mu 太短了。

标签: sql postgresql join count sum


【解决方案1】:

数字太高,因为您要加入 babtissue,然后还要加入 dna,这会导致重复。

你可以试着打破它。我不知道这种语法是否适用于您的数据库,但我相信它遵循 ANSI 标准,所以试一试...

SELECT
    SQ.name,
    SUM(CASE WHEN T.sample_type = 'BLOOD' AND T.avail = 'Y' THEN 1 ELSE 0 END) AS bloodsamps,
    SUM(CASE WHEN T.sample_type = 'TISSUE' AND T.avail = 'Y' THEN 1 ELSE 0 END) AS tissuesamps,
    SQ.gdnas,
    SQ.wgas
FROM
    (
    SELECT
        B.name,
        SUM(CASE WHEN D.sample_type = 'GDNA' AND T.avail = 'Y' THEN 1 ELSE 0 END) AS gdnas,
        SUM(CASE WHEN D.sample_type = 'WGA' AND T.avail = 'Y' THEN 1 ELSE 0 END) AS wgas
    FROM
        biograph B
    LEFT JOIN dna D ON D.name = B.name
    GROUP BY
        B.name
    ) AS SQ
LEFT JOIN babtissue T on T.name = SQ.name
WHERE SQ.name is not NULL
GROUP BY SQ.name, SQ.gdnas, SQ.wgas
ORDER BY SQ.name

名字真的可以为NULL吗?

【讨论】:

  • PostgreSQL 可以处理所有这些。
  • 是的,@Tom H.,名称可以为空。该表中还有其他几列(我试图省略不相关的信息),其中包含人口中出生的每个个体的一行。许多动物在出生后不久就死去,因此从未被命名。我尝试了该查询,它给了我一些我能够修复的小错误。子查询需要一个“GROUP BY B.name”,最后的“GROUP BY”需要我包含 SQ.gdnas 和 SQ.wgas。但是一旦我添加了这些,它就起作用了!谢谢!
  • @Jake:对不起,我应该发现通常的“模糊 GROUP BY”问题,但很容易解决。您可以在汤姆的回答旁边接受clicking the checkmark 的回答。
  • 我已经更正了 GROUP BY 问题。感谢您指出这一点。
【解决方案2】:

我不知道“avail”列,但这应该会为您提供您正在寻找的其他列:

SELECT  b.name,
        COALESCE (t.bloodsamps,  0) AS bloodsamps,
        COALESCE (t.tissuesamps, 0) AS tissuesamps
        COALESCE (d.gdnas, 0) AS gdnas 
        COALESCE (d.wgas,  0) AS wgas
    FROM biograph b
    LEFT JOIN (
        SELECT  name,
                SUM(CASE WHEN sample_type = 'BLOOD'  THEN 1 ELSE 0 END) AS bloodsamps,
                SUM(CASE WHEN sample_type = 'TISSUE' THEN 1 ELSE 0 END) AS tissuesamps
            FROM babtissue
            WHERE avail = 'Y'
            GROUP BY name
        ) t
        ON (t.name = b.name)
    LEFT JOIN (
        SELECT  name,
                SUM(CASE WHEN sample_type = 'GDNA' THEN 1 ELSE 0 END) AS gdnas,
                SUM(CASE WHEN sample_type = 'WGA'  THEN 1 ELSE 0 END) AS wgas
            FROM dna
            WHERE avail = 'Y'
            GROUP BY name
        ) d
        ON (d.name = b.name)
;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    • 1970-01-01
    • 2013-03-21
    • 1970-01-01
    • 2022-10-01
    • 2014-09-16
    • 2013-10-11
    相关资源
    最近更新 更多