我对我正在构建的查询有疑问,我想在SQL语句中完成所有操作。
所以,我有一个这样的数据表:
+-----+-----+-----+-----+
| pid | did | src | val |
+-----+-----+-----+-----+
| 1 | 1 | lab | 0 |
| 1 | 1 | lab | 1 |
| 2 | 3 | pl | 1 |
| 1 | 1 | pl | 1 |
| 2 | 1 | med | 1 |
| 1 | 1 | med | 1 |
+-----+-----+-----+-----+
有一个ID列(pid)和一个疾病列(did),一个source(src)列和一个value(val)列。疾病专栏还有我创建的标准化表格:
+-----+-----------------+
| did | name |
+-----+-----------------+
| 1 | Lung Cancer |
| 2 | Alcoholism |
| 3 | Obesity |
| 4 | Diabetes |
| 5 | Viral Infection |
+-----+-----------------+
这里的真正诀窍是我需要进行一个查询,该查询会生成一个表,该表生成一个显示每个pid(ID)的新表,以及该疾病的相关文本名(did),这可能是一个JOIN使用规范化表格。
棘手的部分是,对于每个ID,我需要计算(3)个可能来源(src)的EACH的出现次数,因此可能会有5-10个ID出现,并且每个出现1个这些将有一个src关联:MED,LAB或PL。我需要按照记录计算这些数据并显示在下面的表格中。
+-----+------------------------+--------------------------+----------------------+
| pid | Lung Cancer | Alcoholism | Obesity
+-----+------------------------+--------------------------+----------------------+
| 1 | Yes | Maybe | No |
| | (med: 2, lab: 1, pl:1) | (med: 0, lab: 1, pl:1) | (med:0, lab:0, pl:0) |
+-----+------------------------+--------------------------+----------------------+
因此可能有5-10行,ID为1,并且对于每一行,将分配一个src(source),它将是三个值之一(lab,pl,med),这些将具有值0 0或1。
最后会有一个计数,基本上有三个状态到达(是)他们有疾病,(每个来源的所有1或以上),或两个零,但是一个人有一个或多个(可能),或全部为零,(不)
我不确定所有这些都可以用SQL语句完成......或者我可以使用JOIN / UNION或某种组合来构建一个新表并放置所有值,然后json_encode它(我' m使用PHP),然后使用Angular对src值进行排序并进行计算并显示"是"," No"的引导按钮。或"可能"
谢谢你们的帮助!这是一个令人费解的SQL语句,或者至少我是这么认为的。
答案 0 :(得分:1)
这很简单,只需按步骤进行..首先卷起src:
SELECT pid, did,
sum(CASE WHEN src='med' THEN val ELSE O END) AS med,
sum(CASE WHEN src='lab' THEN val ELSE O END) AS lab,
sum(CASE WHEN src='pl' THEN val ELSE O END) AS pl
FROM table_of_data
GROUP BY pid, did
现在按照
进入列SELECT pid,
max(CASE WHEN did=1 THEN '(med:'|| CAST(med as varchar(5)) ||
', lab:'|| CASE(lab as varchar(5)) ||
', pl:' || CAST(pl as varhcar(5)) || ')'
ELSE null END) AS Lung_Cancer,
max(CASE WHEN did=2 THEN '(med:'|| CAST(med as varchar(5)) ||
', lab:'|| CASE(lab as varchar(5)) ||
', pl:' || CAST(pl as varhcar(5)) || ')'
ELSE null END) AS Alcoholism,
max(CASE WHEN did=3 THEN '(med:'|| CAST(med as varchar(5)) ||
', lab:'|| CASE(lab as varchar(5)) ||
', pl:' || CAST(pl as varhcar(5)) || ')'
ELSE null END) AS Obesity,
max(CASE WHEN did=4 THEN '(med:'|| CAST(med as varchar(5)) ||
', lab:'|| CASE(lab as varchar(5)) ||
', pl:' || CAST(pl as varhcar(5)) || ')'
ELSE null END) AS Diabetes,
max(CASE WHEN did=5 THEN '(med:'|| CAST(med as varchar(5)) ||
', lab:'|| CASE(lab as varchar(5)) ||
', pl:' || CAST(pl as varhcar(5)) || ')'
ELSE null END) AS Viral_Infection,
FROM prior_result
GROUP BY pid
要得到是否可以使用先前结果中的案例
SELECT pid, did,
CASE WHEN med+lab+pl > 3 THEN 'Yes'
WHEN med+lab+pl = 0 THEN 'No'
ELSE 'Maybe' END AND as have_it
FROM prior_result
没问题......把它们放在一起就可以了
SELECT pid,
max(CASE WHEN did=1 THEN '(med:'|| CAST(med as varchar(5)) ||
', lab:'|| CASE(lab as varchar(5)) ||
', pl:' || CAST(pl as varhcar(5)) || ')'
ELSE null END) AS Lung_Cancer,
max(CASE WHEN did=1 THEN
CASE WHEN med+lab+pl > 3 THEN 'Yes'
WHEN med+lab+pl = 0 THEN 'No'
ELSE 'Maybe'
END
ELSE null END) AS Have_Lung_Cancer,
max(CASE WHEN did=2 THEN '(med:'|| CAST(med as varchar(5)) ||
', lab:'|| CASE(lab as varchar(5)) ||
', pl:' || CAST(pl as varhcar(5)) || ')'
ELSE null END) AS Alcoholism,
max(CASE WHEN did=2 THEN
CASE WHEN med+lab+pl > 3 THEN 'Yes'
WHEN med+lab+pl = 0 THEN 'No'
ELSE 'Maybe'
END
ELSE null END) AS Have_Alcoholism,
max(CASE WHEN did=3 THEN '(med:'|| CAST(med as varchar(5)) ||
', lab:'|| CASE(lab as varchar(5)) ||
', pl:' || CAST(pl as varhcar(5)) || ')'
ELSE null END) AS Obesity,
max(CASE WHEN did=3 THEN
CASE WHEN med+lab+pl > 3 THEN 'Yes'
WHEN med+lab+pl = 0 THEN 'No'
ELSE 'Maybe'
END
ELSE null END) AS Have_Obesity,
max(CASE WHEN did=4 THEN '(med:'|| CAST(med as varchar(5)) ||
', lab:'|| CASE(lab as varchar(5)) ||
', pl:' || CAST(pl as varhcar(5)) || ')'
ELSE null END) AS Diabetes,
max(CASE WHEN did=4 THEN
CASE WHEN med+lab+pl > 3 THEN 'Yes'
WHEN med+lab+pl = 0 THEN 'No'
ELSE 'Maybe'
END
ELSE null END) AS Have_Diabetes,
max(CASE WHEN did=5 THEN '(med:'|| CAST(med as varchar(5)) ||
', lab:'|| CASE(lab as varchar(5)) ||
', pl:' || CAST(pl as varhcar(5)) || ')'
ELSE null END) AS Viral_Infection,
max(CASE WHEN did=5 THEN
CASE WHEN med+lab+pl > 3 THEN 'Yes'
WHEN med+lab+pl = 0 THEN 'No'
ELSE 'Maybe'
END
ELSE null END) AS Have_Viral_Infection,
FROM (
SELECT pid, did,
sum(CASE WHEN src='med' THEN val ELSE O END) AS med,
sum(CASE WHEN src='lab' THEN val ELSE O END) AS lab,
sum(CASE WHEN src='pl' THEN val ELSE O END) AS pl
FROM table_of_data
GROUP BY pid, did
) sub
GROUP BY pid
答案 1 :(得分:0)
看到你可能需要在某些时候动态地计算出所有这些,这是一种获得结果的方法,然后以比@hogan的答案少一点的方式转动,但这是基于他的答案。
SELECT
d.pid
,COALESCE(MAX(CASE WHEN d.did = 1 THEN colString END),'No (med:0 lab:0 pl:0)') as Lung_Cancer
,COALESCE(MAX(CASE WHEN d.did = 2 THEN colString END),'No (med:0 lab:0 pl:0)') as Alcoholism
,COALESCE(MAX(CASE WHEN d.did = 3 THEN colString END),'No (med:0 lab:0 pl:0)') as Obesity
FROM
(
SELECT pid, did,
CONCAT(CASE
WHEN SUM(Val) > 2 THEN 'Yes'
WHEN SUM(Val) > 1 THEN 'Maybe'
ELSE 'No'
End
,' (med:'
,CAST(SUM(CASE WHEN src='med' THEN val ELSE 0 END) AS CHAR(5))
,' lab:'
,CAST(SUM(CASE WHEN src='lab' THEN val ELSE 0 END) AS CHAR(5))
,' pl:'
,CAST(SUM(CASE WHEN src='pl' THEN val ELSE 0 END) AS CHAR(5))
,')') as colString
FROM TableP
GROUP BY pid, did
) d
GROUP BY
d.pid
请注意,当特定疾病的PID没有值时,使用COALESCE会处理。 sql小提琴:http://www.sqlfiddle.com/#!9/44ac9/11
只是为了向您展示它可以在没有子查询的情况下完成:
SELECT
pid
,CONCAT(CASE
WHEN SUM(CASE WHEN did = 1 THEN val ELSE 0 END) > 2 THEN 'Yes'
WHEN SUM(CASE WHEN did = 1 THEN val ELSE 0 END) > 1 THEN 'Maybe'
ELSE 'No'
END
, ' (med:'
,CAST(SUM(CASE WHEN did = 1 and src = 'med' THEN val ELSE 0 END) AS CHAR(5))
, ', lab:'
,CAST(SUM(CASE WHEN did = 1 and src = 'lab' THEN val ELSE 0 END) AS CHAR(5))
, ', pl:'
,CAST(SUM(CASE WHEN did = 1 and src = 'pl' THEN val ELSE 0 END) AS CHAR(5))
,')' ) AS Lung_Cancer
.......repeat per disease
FROM
table_of_data
GROUP BY
pid
这种技术的SQL小提琴http://www.sqlfiddle.com/#!9/44ac9/13
答案 2 :(得分:0)
由于你也有一定数量的有效来源,你也应该有一张桌子:
+-----+-----+ | src | pos | +-----+-----+ | lab | 2 | | med | 1 | | pl | 3 | +-----+-----+
(列pos
表示您希望显示源的结果中的哪个位置。)
然后交叉加入疾病和来源以获得所有组合。外部连接数据表以获得所需的pid和每个desease和source的计数。其余的主要是字符串连接:
set @pid = 1;
select
pid,
name,
concat
(
case when count(sumval) <> count(*) then 'Maybe'
when min(sumval) > 0 then 'Yes'
when max(sumval) = 0 then 'No'
else 'Maybe'
end,
' (',
group_concat(concat(src, ': ', coalesce(sumval, '?')) order by pos separator ', '),
')'
) as result
from
(
select @pid as pid, d.*, s.*, sum(data.val) as sumval
from desease d
cross join source s
left join data on data.did = d.did
and data.src = s.src
and data.pid = @pid
group by d.did, s.src
) sumvals
group by did
having count(sumval) > 0;
这为您提供了如下行:
+-----+-----------------+-------------------------------+ | pid | name | result | +-----+-----------------+-------------------------------+ | 1 | Lung Cancer | Yes (med: 2, lab: 1, pl: 1) | | 1 | Alcoholism | Maybe (med: 0, lab: 1, pl: 1) | | 1 | Obesity | No (med: 0, lab: 0, pl: 0) | +-----+-----------------+-------------------------------+
如果没有pid,desease和source的条目,我们不知道desease是否适用。在这种情况下,sumval
为空。如果一个desease甚至没有一个条目,那么我们根本就不显示它(参见having
子句)。否则,如果至少有一个来源和另一个缺失,我们会得出'Maybe'。
这是SQL小提琴:http://sqlfiddle.com/#!9/c2ac29/1
GUI层的任务是关心布局(在您的情况下:以列显示结果)。