Functions

SQL 級別的計算

  • November 1, 2018

我有這個查詢:

SELECT *
FROM (
 SELECT COUNT(lead_status) as 'Pending files'
 FROM vw_file_registrationlist
 WHERE lead_status_id = "1" || lead_status_id="2" || lead_status_id="4" || lead_status_id="5" || lead_status_id="6"
)A,
(
 SELECT COUNT(lead_status) as 'Completed files'
 FROM vw_file_registrationlist
 WHERE lead_status_id = "3"
)B
, (
 select DISTINCT employee_name
 From vw_file_registrationlist
 where employee_name='anna'
)C

我得到的結果是

名稱 待處理文件 已完成文件
---- ------------- ---------------
安娜 3 2

我需要計算pending files / total files * 100. 可能嗎?

這不對,

WHERE lead_status_id = "1" || lead_status_id="2" || lead_status_id="4" || lead_status_id="5" || lead_status_id="6"

你想要的是,

WHERE lead_status_id IN (1,2,4,5,6);

認真地,學習使用空格並為您的程式碼感到自豪。選擇一個約定(將所有 sql 標記大寫,並將所有標識符小寫)即使你沒有得到這樣寫的 sql..

)a
)b

你是從哪裡得到的?..SELECT (...) AS t, (...) AS x空格和AS! 說了這麼多,我想你想要這樣的東西,

SELECT
 count(lead_status) FILTER (WHERE lead_status_id IN (1,2,4,5,6)) as 'Pending files',
 count(lead_status) FILTER (WHERE lead_status_id = 3) AS 'Completed files',
 any(employee_name = 'anna') AS has_anna
FROM vw_file_registrationlist;

您提供了對提供您正在使用的 DBMS 的請求的答复,這使得提供絕對適合您的 SQL 變得困難。

無論 DBMS 是什麼,類似於 Even Carroll 提出的東西應該​​比您的原始查詢執行得更好,因為它執行的是單個查詢,而不是三個單獨的查詢。

我將把他的查詢改寫成我認為更通用的形式(我通常在 SQL Server 中工作,我不認為他所做的一切都在那里工作)。

SELECT 'anna' as [Name]
     ,SUM(CASE WHEN lead_status IS NULL THEN 0
               WHEN lead_status_id IN (1,2,4,5,6) THEN 1
               ELSE 0 END) AS 'Pending files'
     ,SUM(CASE WHEN lead_status IS NULL THEN 0
               WHEN lead_status_id = 3 THEN 1
               ELSE 0 END) AS 'Completed files'
 FROM vw_file_registrationlist
WHERE EXISTS (SELECT 1 FROM vw_file_registrationlist WHERE employee_name = 'anna')
;

現在,這應該執行以下操作:

  • 如果沒有記錄 where employee_nameis 'anna',則不返回任何行。

  • 否則,它返回:

    • 'anna'
    • 為 1、2、4、5lead_status_id或 6lead_status且不為 NULL的行數
    • 行數 wherelead_status_id為 3,且 wherelead_status不為 NULL

COUNT()函式在對單個列(而不是COUNT(*))進行操作時,會計算該列的非 NULL 出現次數。由於我正在使用CASE語句過濾數據並SUM為應該計算的每一行計算值 1,因此我需要確保我沒有lead_status手動計算為 NULL 的行。如果您想要所有行,無論是否lead_status為NULL,或者是否lead_statusNOT NULL列,您都可以消除WHEN lead_status IS NULL THEN 0部分。

好的,現在來獲取您的計算值。你有兩個選擇:

使用等式中的聚合函式直接計算值:

SELECT 'anna' as [Name]
     ,SUM(CASE WHEN lead_status IS NULL THEN 0
               WHEN lead_status_id IN (1,2,4,5,6) THEN 1
               ELSE 0 END) AS 'Pending files'
     ,SUM(CASE WHEN lead_status IS NULL THEN 0
               WHEN lead_status_id = 3 THEN 1
               ELSE 0 END) AS 'Completed files'
     , SUM(CASE WHEN lead_status IS NULL THEN 0
                WHEN lead_status_id IN (1,2,4,5,6) THEN 1
                ELSE 0 END)
      /SUM(CASE WHEN lead_status IS NULL THEN 0
                WHEN lead_status_id = 3 THEN 1
                ELSE 0 END)
      *100 AS 'Calculated Value'
 FROM vw_file_registrationlist
WHERE EXISTS (SELECT 1 FROM vw_file_registrationlist WHERE employee_name = 'anna')
;

這應該會給你你想要的答案。但是,從維護的角度來看,這並不是很好(如果掛起或已完成文件的定義發生變化,您必須進行兩次更改),並且很難遵循。所以,還有:

將查詢包裝在另一個查詢中以執行最終計算:

SELECT employee_name AS 'Name'
     ,pending_count AS 'Pending files'
     ,completed_count AS 'Completed files'
     ,(pending_count * 100 / completed_count) AS `Calculated value'
 FROM (
       SELECT 'anna' as employee_name
             ,SUM(CASE WHEN lead_status IS NULL THEN 0
                       WHEN lead_status_id IN (1,2,4,5,6) THEN 1
                       ELSE 0 END) AS pending_count
             ,SUM(CASE WHEN lead_status IS NULL THEN 0
                       WHEN lead_status_id = 3 THEN 1
                       ELSE 0 END) AS completed_count
         FROM vw_file_registrationlist
        WHERE EXISTS (SELECT 1 FROM vw_file_registrationlist WHERE employee_name = 'anna')
  ) t
;

這只是讓您使用子查詢中的列名編寫方程,而不必使用完整的聚合表達式。由於表達式現在只使用一次,潛在的維護問題就消失了。另外,這更具可讀性。

任何一個都應該工作。有可能其中一個會表現得更好;如果要返回大量行(而不是像您的範例中那樣的一行),則第一個選項(直接在計算中使用聚合值)可能會執行得更好。也就是說,即使這樣,差異也可能足夠小,以至於第二種選擇的維護優勢可能會使其在實踐中變得更好。

引用自:https://dba.stackexchange.com/questions/195755