繁体   English   中英

如何在MySQL中针对特定条件进行嵌套查询

[英]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和/或使用包含其他IFIFNULLNULLIF函数的表达式。


跟进

这个问题尚不清楚所需的结果集。

上面的答案基于这样的假设:期望的结果是另外一列,其中包含当年内具有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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM