簡體   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