[英]How to make a nested query for a specific condition in MySQL
我进行了此查询,在其中可以获取按状态显示的项目列表,并获取每个状态的数量。 这是查询:
SELECT DISTINCT (status) AS Status, COUNT(status) AS Quantity
FROM projects
GROUP BY status
ORDER BY Quantity DESC
结果如下:
Status Quantity
'PRO', 238
'TER', 75
'SUS', 14
'REI', 3
现在,对于那些具有“ TER”状态的产品,我想获得今年已更新或修改的那些“ TER”状态,并将它们添加到结果中(不包括往年的那些“ TER”产品)。 为此,我需要将此列updated_at
(可以这么说)。
如何过滤这些值?
例如,我尝试过:
SELECT DISTINCT (status) AS Status, COUNT(status) AS Quantity,
IF(status='TER',SELECT * FROM projects WHERE year(updated_at)=YEAR(CURDATE()))
FROM projects
GROUP BY status
ORDER BY Quantity DESC
但这没有用。
有任何想法吗?
感谢您的想法。
可能的解决方案 :
我已经通过使用UNION找到了另一种解决方案:
(SELECT DISTINCT (status) AS Status, COUNT(status) AS Quantity,
IF(status='TER',SELECT * FROM projects WHERE year(updated_at)=YEAR(CURDATE()))
FROM projects
GROUP BY status
ORDER BY Quantity DESC)
UNION
(
SELECT DISTINCT (status) AS Status, COUNT(status) AS Quantity,
IF(status='TER',SELECT * FROM projects WHERE year(updated_at)=YEAR(CURDATE()))
FROM projects
WHERE year(updated_at) = YEAR(curdate())
AND status IN ('TER')
GROUP BY status
ORDER BY Quantity DESC
)
因此,现在我将那些项目设为“ TER”状态,并且只将其当年。
因此,“ TER”的过滤器结果现在为(应该是更少的结果):
Status Quantity
'PRO', 238
'SUS', 14
'REI', 3
'TER', 45
现在的问题是我需要重新排列结果,我的意思是,'TER'应该排在第二位...好吧,我刚刚在这里找到了。
所以我的最终查询是:
SELECT * FROM (
(SELECT DISTINCT (status) AS Status, COUNT(status) AS Quantity,
IF(status='TER',SELECT * FROM projects WHERE year(updated_at)=YEAR(CURDATE()))
FROM projects
GROUP BY status
ORDER BY Quantity DESC)
UNION
(
SELECT DISTINCT (status) AS Status, COUNT(status) AS Quantity,
IF(status='TER',SELECT * FROM projects WHERE year(updated_at)=YEAR(CURDATE()))
FROM projects
WHERE year(updated_at) = YEAR(curdate())
AND status IN ('TER')
GROUP BY status
ORDER BY Quantity DESC
)
) a
GROUP BY status
ORDER BY Quantity DESC
现在,我得到了想要的结果并订购了desc:
Status Quantity
'PRO', 238
'TER', 45
'SUS', 14
'REI', 3
还是有更好的出路?
根据对问题的编辑(现在可以更好地解释预期的结果),我用其他查询更新了此答案。 我仍然建议条件聚合 。
SELECT p.status AS Status
, COUNT( IF( p.status = 'TER'
, IF( YEAR(p.updated_at) = YEAR(CURDATE())
, 1
, NULL
)
, 1
)
) AS Quantity
FROM projects p
GROUP BY p.status
ORDER BY Quantity DESC
不需要换行和间隔...我只是这样做,以使其更易于解密。
对于status = 'TER'
的行,仅当满足updated_at
的条件时,该行才包含在“计数”中。 对于status
所有其他值,该行包含在该状态的“ count”中。
MySQL特定的表达式:
IF( p.status = 'TER'
, IF( YEAR(p.updated_at) = YEAR(CURDATE())
, 1
, NULL
)
, 1
)
可以用更符合ANSI标准的表达式代替,例如:
CASE WHEN p.status = 'TER'
CASE WHEN YEAR(p.updated_at) = YEAR(CURDATE()
THEN 1
END
ELSE 1
END
原始答案
还不清楚您想要返回什么结果。
看起来您希望返回一个附加列,并且看起来您可能希望该列成为“数量”列中所包含行的子集的“计数”。 我们能做到这一点。
但是首先,让我们解决原始查询的一些问题。
关键字DISTINCT
是不必要的,它与GROUP BY
无关。 并且无需在引用status
旁注。 这样做不是违法的,但是它什么也没做,所以很混乱。 它看起来好像有人认为DISTINCT
是一个函数。 不是。 这是一个关键字,适用于整个SELECT
列表。
SELECT p.status AS Status
, COUNT(p.status) AS Quantity
FROM projects p
GROUP BY p.status
ORDER BY Quantity DESC
似乎您要进行条件汇总...如果updated_at
是当前年份中的日期或日期时间,则将其包括在计数中,否则不包括在内。
SELECT p.status AS Status
, COUNT(p.status) AS Quantity
, SUM(IF(p.status = 'TER' AND YEAR(p.updated_at)=YEAR(CURDATE()),1,NULL)) AS curcnt
FROM projects p
GROUP BY p.status
ORDER BY Quantity DESC
表达方式:
IF(p.status = 'TER' AND YEAR(p.updated_at)=YEAR(CURDATE()),1,NULL)
是MySQL的简写。 使用更符合ANSI标准的表达式可以获得等效的结果:
CASE WHEN p.status = 'TER' AND YEAR(p.updated_at)=YEAR(CURDATE()) THEN 1 END
根据您希望在该行和其他行上显示“零”计数的方式,您可能希望使用0
代替NULL
和/或使用包含其他IF
, IFNULL
或NULLIF
函数的表达式。
跟进
这个问题尚不清楚所需的结果集。
上面的答案基于这样的假设:期望的结果是另外一列,其中包含当年内具有status='TER'
和updated_at
的行的“计数”。
上面的答案演示了条件聚合 ,并且没有使用“嵌套查询”。
“嵌套查询”可用于获取等效结果。
作为使用“嵌套查询”作为内联视图的示例:
SELECT p.status AS Status
, COUNT(p.status) AS Quantity
, NULLIF(MAX(q.curcnt),0) AS curcnt
FROM projects p
LEFT
JOIN ( SELECT r.status
, COUNT(1) AS curcnt
FROM projects r
WHERE r.status = 'TER'
AND YEAR(r.updated_at) = YEAR(NOW())
GROUP BY r.status
) q
ON q.status = p.status
GROUP BY p.status
ORDER BY Quantity DESC
并以“嵌套查询”作为SELECT列表中的子查询的示例:
SELECT p.status AS Status
, COUNT(p.status) AS Quantity
, NULLIF( SELECT COUNT(1)
FROM projects r
WHERE r.status = p.status
AND r.status = 'TER'
AND YEAR(r.updated_at) = YEAR(NOW())
,0) AS curcnt
FROM projects p
GROUP BY p.status
ORDER BY Quantity DESC
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.