PostgreSQL中跨多个表的多个总和/计数
我已经在这个网站上搜索了好几条建议,还没有完全得到我想要的。我怀疑我只是遗漏了一个语法/标点符号问题 我使用phpPgAdmin开发了一个数据库,该数据库跟踪了大量与正在研究的狒狒种群相关的信息。我试图通过查询来确定,对于每只狒狒,我们为它们采集了多少不同类型的组织样本,以及我们为每只狒狒采集了多少不同类型的DNA样本。有三个表与我的问题相关: 表:“biograph”包含了该组中所有动物的基本信息,尽管这里我只关心它们的名字PostgreSQL中跨多个表的多个总和/计数,sql,postgresql,join,count,sum,Sql,Postgresql,Join,Count,Sum,我已经在这个网站上搜索了好几条建议,还没有完全得到我想要的。我怀疑我只是遗漏了一个语法/标点符号问题 我使用phpPgAdmin开发了一个数据库,该数据库跟踪了大量与正在研究的狒狒种群相关的信息。我试图通过查询来确定,对于每只狒狒,我们为它们采集了多少不同类型的组织样本,以及我们为每只狒狒采集了多少不同类型的DNA样本。有三个表与我的问题相关: 表:“biograph”包含了该组中所有动物的基本信息,尽管这里我只关心它们的名字 name | birth -----+----------- A21
name | birth
-----+-----------
A21 | 1968-07-01
AAR | 2002-03-30
ABB | 1998-09-10
ABD | 2005-03-15
ABE | 1986-01-01
表:“BabTisson”记录了多年来收集的不同组织的信息,包括以下三列。此表中的某些行表示我们不再拥有的组织样本,但仍在数据库中的其他位置引用,因此“avail”列帮助我们筛选我们仍然拥有的样本
name | sample_type | avail
-----+-------------+------
A21 | BLOOD | Y
A21 | BLOOD | Y
A21 | TISSUE | N
ABB | BLOOD | Y
ABB | TISSUE | Y
表:“dna”与巴氏组织相似
name | sample_type | avail
-----+-------------+------
ABB | GDNA | N
ABB | WGA | Y
ACC | WGA | N
ALE | GDNA | Y
ALE | GDNA | Y
总之,我试图写一个查询,返回biograph中的每个名字,并在一列中告诉我每个人有多少“血液”、“组织”、“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
这样做时我没有收到任何错误,但我知道它给我的数字是错误的——太高了。我想这与我使用多个连接有关,我的连接语法需要改变
有什么想法吗?这些数字太高了,因为你要加入
BabTisson
,然后加入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
名称真的可以为空吗?我不知道“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)
;
我整理了你的格式,但我不确定你在
avail
列中想要什么,所以我把?
放在那里。谢谢你,@mu太短了。PostgreSQL可以处理所有这些。是的,@Tom H.,name可以为空。该表中还有其他几列(我试图省略不相关的信息),其中包括人口中出生的每个人的一行。许多动物出生后不久就死了,因此从来没有人给它们起过名字。我尝试了一下这个查询,它给了我一些小错误,我能够修复它们。子查询需要一个“groupby B.name”,最后的“groupby”需要我包含SQ.gdnas和SQ.wgas。但一旦我添加了这些,它就成功了!谢谢@杰克:对不起,我本应该发现常见的“模棱两可的分组方式”问题,但很容易解决。你可以在Tom的答案旁边接受答案。我已经纠正了分组方式的问题。谢谢你指出这一点。