[英]How to make a nested query for a specific condition in MySQL
I have made this query where I get a list of items by their statuses and get the quantities for each status. 我进行了此查询,在其中可以获取按状态显示的项目列表,并获取每个状态的数量。 Here is the query: 这是查询:
SELECT DISTINCT (status) AS Status, COUNT(status) AS Quantity
FROM projects
GROUP BY status
ORDER BY Quantity DESC
And here are the results: 结果如下:
Status Quantity
'PRO', 238
'TER', 75
'SUS', 14
'REI', 3
Now for those that have a 'TER' status, I want to get those 'TER' statuses that were updated or modified this year and add them to the results (excluding those 'TER' from previous years). 现在,对于那些具有“ TER”状态的产品,我想获得今年已更新或修改的那些“ TER”状态,并将它们添加到结果中(不包括往年的那些“ TER”产品)。 To do this, I have this column updated_at
(so to speak). 为此,我需要将此列updated_at
(可以这么说)。
How can I filter those values? 如何过滤这些值?
For example, I have tried: 例如,我尝试过:
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
But it didn't work. 但这没有用。
Any ideas? 有任何想法吗?
Thanks for the ideas. 感谢您的想法。
Posible solution : 可能的解决方案 :
I have figured out another solution by using UNION: 我已经通过使用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
)
So now I get those projects in 'TER' status and only those within the current year. 因此,现在我将那些项目设为“ TER”状态,并且只将其当年。
So the filter results for 'TER' are now (and should be less results): 因此,“ TER”的过滤器结果现在为(应该是更少的结果):
Status Quantity
'PRO', 238
'SUS', 14
'REI', 3
'TER', 45
The problem now is that I need to reorder the results, I mean, 'TER' should be in second place... well, I have just found out here . 现在的问题是我需要重新排列结果,我的意思是,'TER'应该排在第二位...好吧,我刚刚在这里找到了。
So my final query is: 所以我的最终查询是:
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
And now I get the results I want and ordered desc: 现在,我得到了想要的结果并订购了desc:
Status Quantity
'PRO', 238
'TER', 45
'SUS', 14
'REI', 3
Or is there a better way out there? 还是有更好的出路?
Based on the edit to the question, which now better explains the expected result, I've updated this answer with a different query. 根据对问题的编辑(现在可以更好地解释预期的结果),我用其他查询更新了此答案。 I still recommend conditional aggregation . 我仍然建议条件聚合 。
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
The line breaks and spacing aren't required... I just do that to make it easier to decipher. 不需要换行和间隔...我只是这样做,以使其更易于解密。
For a row that has status = 'TER'
, it is included in the "count" only if the condition on updated_at
is satisfied. 对于status = 'TER'
的行,仅当满足updated_at
的条件时,该行才包含在“计数”中。 For all other values of status
, the row is included in the "count" for that status. 对于status
所有其他值,该行包含在该状态的“ count”中。
The MySQL-specific expression: MySQL特定的表达式:
IF( p.status = 'TER'
, IF( YEAR(p.updated_at) = YEAR(CURDATE())
, 1
, NULL
)
, 1
)
Could be replaced with a more ANSI standards compliant expression, for example: 可以用更符合ANSI标准的表达式代替,例如:
CASE WHEN p.status = 'TER'
CASE WHEN YEAR(p.updated_at) = YEAR(CURDATE()
THEN 1
END
ELSE 1
END
ORIGINAL ANSWER 原始答案
What's not clear is what result you want returned. 还不清楚您想要返回什么结果。
It looks like you want an additional column returned, and it looks like you might want that to be a "count" of a subset of the rows included in the "Quantity" column. 看起来您希望返回一个附加列,并且看起来您可能希望该列成为“数量”列中所包含行的子集的“计数”。 We can do that. 我们能做到这一点。
But first, let's fix some issues with the original query. 但是首先,让我们解决原始查询的一些问题。
The keyword DISTINCT
is not necessary, it's redundant with the GROUP BY
. 关键字DISTINCT
是不必要的,它与GROUP BY
无关。 And there's no need for parens around the reference to status
. 并且无需在引用status
旁注。 That's not illegal to do that, but it doesn't do anything, so it's just confusing. 这样做不是违法的,但是它什么也没做,所以很混乱。 It makes it look as if someone believes that DISTINCT
is a function. 它看起来好像有人认为DISTINCT
是一个函数。 It's not. 不是。 It's a keyword that applies to the entire SELECT
list. 这是一个关键字,适用于整个SELECT
列表。
SELECT p.status AS Status
, COUNT(p.status) AS Quantity
FROM projects p
GROUP BY p.status
ORDER BY Quantity DESC
It looks like you want conditional aggregation... if the updated_at
is a date or datetime in the current year, then include it in the count, otherwise don't. 似乎您要进行条件汇总...如果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
The expression: 表达方式:
IF(p.status = 'TER' AND YEAR(p.updated_at)=YEAR(CURDATE()),1,NULL)
is MySQL shorthand. 是MySQL的简写。 An equivalent result could be obtained with a more ANSI standards compliant expression: 使用更符合ANSI标准的表达式可以获得等效的结果:
CASE WHEN p.status = 'TER' AND YEAR(p.updated_at)=YEAR(CURDATE()) THEN 1 END
Depending on how you want a count of "zero" to be displayed on that row, and other rows, you might want to use 0
in place of NULL
, and/or use an expression that includes additional IF
, IFNULL
or NULLIF
functions. 根据您希望在该行和其他行上显示“零”计数的方式,您可能希望使用0
代替NULL
和/或使用包含其他IF
, IFNULL
或NULLIF
函数的表达式。
FOLLOWUP 跟进
The desired resultset is not clear from the question. 这个问题尚不清楚所需的结果集。
The answer above is based on the assumption that the desired result is an additional column that contains a "count" of the rows that have status='TER'
and updated_at
within the current year. 上面的答案基于这样的假设:期望的结果是另外一列,其中包含当年内具有status='TER'
和updated_at
的行的“计数”。
The answer above demonstrates conditional aggregation , and does not make use of a "nested query". 上面的答案演示了条件聚合 ,并且没有使用“嵌套查询”。
A "nested query" could be used to obtain an equivalent result. “嵌套查询”可用于获取等效结果。
As an example of using a "nested query" as an inline view: 作为使用“嵌套查询”作为内联视图的示例:
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
And as an example of a "nested query" as a subquery in the SELECT list: 并以“嵌套查询”作为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.