如何在MySQL

时间:2016-03-10 19:33:54

标签: 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'应该排在第二位......好吧,我刚刚找到了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

或者有更好的方法吗?

1 个答案:

答案 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,和/或使用表达式其中包括其他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