我已经进行了此查询,我按状态获取项目列表,并获取每种状态的数量。 这是查询:
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'应该排在第二位......好吧,我刚刚找到了here。
所以我最后的询问是:
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
或者有更好的方法吗?
答案 0 :(得分:2)
基于对问题的编辑,现在更好地解释了预期的结果,我用不同的查询更新了这个答案。我仍然建议条件聚合。
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
的所有其他值,该行包含在该状态的“计数”中。
特定于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
的引用周围不需要parens。这样做并不违法,但它没有做任何事情,所以这只是令人困惑。它使人看起来好像有人认为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