我编写了一个相当复杂的SQL查询来获取动物采样数据库中动物的一些统计数据。此查询包含许多子查询,我现在想看看是否可以以任何方式重写此查询以使用连接而不是子查询。我有一个暗淡的想法,这可能会减少查询时间。 (现在在mac mini上大约23秒)。
以下是查询:
SELECT COUNT(DISTINCT a.AnimalID), TO_DAYS(a.VisitDate) AS day,
DATE_FORMAT(a.VisitDate, '%b %d %Y'), a.origin,
(
SELECT COUNT(DISTINCT a.AnimalID)
FROM samples AS a
JOIN
custom_animals AS b
ON a.AnimalID = b.animal_id
WHERE
b.organism = 2
AND
TO_DAYS(a.VisitDate) = day
) AS Goats,
(
SELECT COUNT(DISTINCT a.AnimalID)
FROM samples AS a
JOIN custom_animals AS b
ON a.AnimalID = b.animal_id
WHERE
b.organism = 2
AND
b.sex = 'Female'
AND
TO_DAYS(a.VisitDate) = day
) AS GF,
(
SELECT COUNT(DISTINCT a.AnimalID)
FROM samples AS a
JOIN custom_animals AS b
ON a.AnimalID = b.animal_id
WHERE
b.organism = 3
AND
b.sex = 'Female'
AND
TO_DAYS(a.VisitDate) = day
) AS SF
FROM
samples AS a
JOIN custom_animals AS b
ON a.AnimalID = b.animal_id
WHERE
project = 5
AND
AnimalID LIKE 'AVD%'
GROUP BY
TO_DAYS(a.VisitDate);
感谢ksogor我的查询现在更快了;
SELECT DATE_FORMAT(s.VisitDate, '%b %d %Y') AS date,
s.origin,
SUM(IF(project = 5 AND s.AnimalID LIKE 'AVD%', 1, 0)) AS sampled_animals,
SUM(IF(ca.organism = 2, 1, 0)) AS sampled_goats,
SUM(IF(ca.organism = 2 AND ca.sex = 'Female', 1, 0)) AS female_goats,
SUM(IF(ca.organism = 3 AND ca.sex = 'Female', 1, 0)) AS female_sheep
FROM samples s JOIN custom_animals ca ON s.AnimalID = ca.animal_id
GROUP BY date;
我仍然需要让这个查询选择不同的s.AnimalID,尽管现在它计算我们从这些动物而不是动物本身采集的样本。有人有任何想法吗?
在ksogor获得更多帮助之后,我现在有了一个很棒的问题:
SELECT DATE_FORMAT(s.VisitDate, '%b %d %Y') AS date,
s.origin,
SUM(IF(project = 5 AND s.AnimalID LIKE 'AVD%', 1, 0)) AS sampled_animals,
SUM(IF(ca.organism = 2, 1, 0)) AS sampled_goats,
SUM(IF(ca.organism = 2 AND ca.sex = 'Female', 1, 0)) AS female_goats,
SUM(IF(ca.organism = 3 AND ca.sex = 'Female', 1, 0)) AS female_sheep
FROM (
SELECT DISTINCT AnimalID AS AnimalID,
VisitDate,
origin,
project
FROM samples
) s
JOIN custom_animals ca ON s.AnimalID = ca.animal_id
GROUP BY date;
答案 0 :(得分:2)
您可以使用if
或case
语句,如下所示:
SELECT SUM(if(project = 5 AND AnimealID LIKE 'AVD%', 1, 0)) AS countbyproj,
TO_DAYS(s.VisitDate) AS day,
DATE_FORMAT(s.VisitDate, '%b %d %Y') AS date,
s.origin,
SUM(if(ca.organism = 2, 1, 0)) AS countGoats,
SUM(if(ca.organism = 2 AND ca.sex = 'Female', 1, 0)) AS countGF,
SUM(if(ca.organism = 3 AND ca.sex = 'Female', 1, 0)) AS countSF
FROM samples s JOIN custom_animals ca ON s.AnimalID = ca.animal_id
GROUP BY TO_DAYS(a.VisitDate);
我无法检查查询,我不知道您期望的结果以及您拥有的表/关系,所以这只是一个有想法的示例。
如果您需要每天计算unque AnimealID:
SELECT SUM(byproj) AS countbyproj,
day,
date,
origin,
SUM(Goats) AS countGoats,
SUM(GF) AS countGF,
SUM(SF) AS countSF
FROM (
SELECT s.AnimealID,
if(project = 5 AND AnimealID LIKE 'AVD%', 1, 0) AS byproj,
TO_DAYS(s.VisitDate) AS day,
DATE_FORMAT(s.VisitDate, '%b %d %Y') AS date,
s.origin,
if(ca.organism = 2, 1, 0)) AS Goats,
if(ca.organism = 2 AND ca.sex = 'Female', 1, 0) AS GF,
if(ca.organism = 3 AND ca.sex = 'Female', 1, 0) AS SF
FROM samples s JOIN custom_animals ca ON s.AnimalID = ca.animal_id
) dataset
GROUP BY dataset.day, dataset.AnimealID;