2017-03-16 92 views
0
SELECT month(dateofappointment), COUNT(*) 'NumberOfAppointments' 
    FROM appointment 
    WHERE YEAR(dateofappointment) = '2016' 
    GROUP BY MONTH(dateofappointment) 

這顯示我所有月份,但十二月不存在,因爲那一年沒有任何約會。我如何顯示12月爲0?每月約會,12月失蹤?

回答

0

要解決這些類型的查詢往往有助於將它們表達爲一系列要求,這可以使其更容易解決。

當結果沒有達到理想的效果,請用新的要求您的要求語句識別它們,然後再試一次:

在我看來,現在你有2個要求:

  1. 返回一個單獨的行,2016年
  2. 每一行的一年中每個月顯示約會的次數對應月份

Ø k因此這是一個冗長的內容,但是你看到你在查詢中缺少的是一個聲明,它定義了'2016年每個月的1行'所以你需要先手動或者通過遞歸構建記錄集。

的MySQL目前不支持遞歸公用表表達式,這在許多其它RDBMS

一個簡單的概念,但是如果MySQL不支持遞歸,我們有什麼選擇?這裏有一些其他的嘗試上SO:

這聽起來有點劈的,但你可以在你的數據庫中有更多使用任何表比12行,並有一個自動遞增的領域,哦,並被播種開始在1(或以下)。忘記這是否是正確的還是錯誤的,它會工作:

SELECT Id 
FROM LogEvent -- An arbitrary table that I know has records starting from 1 
WHERE Id BETWEEN 1 AND 12 

所以這是哈克,但我們可以實現一個行計數功能,使我們可以使用任何表有12個或更多的行,而不管的id或播種,偷來的:MySQL get row number on select - Answer by Mike Cialowicz

SET @rank=0; 
SELECT @rank:[email protected]+1 AS rank 
FROM orders 
WHERE rank <= 12 

現在,我們可以從工會這個結果缺少的行設置爲原始查詢,或者使用一個連接操作。首先使用union的解決方案

使用UNION ALL將缺失的行注入到記錄集是很常見的,因爲它將預期結果查詢從異常或默認結果中分離出來。有時,這句法使得它更容易解釋的預期操作

SET @rank = 0; 

SELECT month(dateofappointment) as Month, COUNT(*) 'NumberOfAppointments' 
FROM appointment 
WHERE YEAR(dateofappointment) = '2016' 
GROUP BY MONTH(dateofappointment) 

UNION ALL 

SELECT rank, 0 
FROM (
    SELECT @rank:[email protected]+1 AS rank 
    FROM rows 
    WHERE @rank < 12 
) months 
WHERE NOT EXISTS (SELECT dateofappointment 
        FROM appointment 
        WHERE YEAR(dateofappointment) = '2016' AND MONTH(dateofappointment) = months.rank) 
ORDER BY Month 

但它使一個醜陋查詢。您也可以加入月數查詢,並在約會次數上加入左連接,但這裏的意圖很難識別。

SET @rank = 0; 

SELECT months.rank, COUNT(appointment.dateofappointment) 
FROM (
    SELECT @rank:[email protected]+1 AS rank 
    FROM rows 
    WHERE @rank < 12 
) months 
LEFT OUTER JOIN appointment ON months.rank = Month(appointment.dateofappointment) AND YEAR(dateofappointment) = '2016' 
GROUP BY months.rank 

I have saved these queries into a SqlFiddle so you can see the resultshttp://sqlfiddle.com/#!9/99d485/4

正如我上面指出的那樣,這是在MS SQL和Oracle RDBMS,在這裏我們可以動態地通過遞歸公用表表達式(CTE的)對於生成值序列瑣碎這裏的家庭玩家是MS SQL Server 2014中的一個實現。該示例稍微更加演化,使用from和from date來動態過濾結果

-- Dynamic MS SQL Example using recursive CTE 
DECLARE @FromDate Date = '2016-01-01' 
DECLARE @ToDate Date = '2016-12-31' 
; 
WITH Months(Year, Month, Date) AS 
(
    SELECT Year(@FromDate), Month(@FromDate), @FromDate 
    UNION ALL 
    SELECT Year(NextMonth.Date), Month(NextMonth.Date), NextMonth.Date 
    FROM Months 
    CROSS APPLY (SELECT DateAdd(m, 1, Date) Date) NextMonth 
    WHERE NextMonth.Date < @ToDate 
) 
SELECT Months.Year, Months.Month, COUNT(*) as 'NumberOfAppointments' 
FROM Months 
LEFT OUTER JOIN appointment ON Year(dateofappointment) = Months.Year AND Month(dateofappointment) = Months.Month 
GROUP BY Months.Year, Months.Month 
+0

我使用union實現了您的第一個查詢,並且我仍然得到了相同的結果:12月份丟失了。 – maia

+0

如果你自己運行rownunber例子(所以嵌套查詢),你會得到12行?我有這些例子都運行在MySQL與預期的結果。我會嘗試設置一個sqlfiddle –

+0

@maia看到這個小提琴http://sqlfiddle.com/#!9/99d485/4我會編輯這個答案以及包括輸出 –