2016-11-16 4 views
1

У меня есть таблица [MY_TABLE] со следующими датами: датой [DOCUMENT_DATE] и статусом [STATUS]. Я хочу разделить и подсчитать статус 3-х разрядов: открыть статус < 8, потерянный при статусе = 8 или выиграть при статусе> 8 при группировке по месяцам и годам.Как группировать по месяцам и годам, а также отделять записи?

Конечный результат будет примерно таким: year, month, count(won), count(lost), count(open), эффективно оценивая количество каждого состояния за каждый месяц.

несколько месяцев не имеют статуса на всех (можно пренебречь), а некоторые имеют только определенный статус и не все из них (следует писать месяц и год правильно)

У меня есть рабочий запрос прямо сейчас, но это действительно огромный:

SELECT 
CASE WHEN "open".year IS NOT NULL 
    THEN 
     "open".year 
    ELSE 
    (CASE WHEN "lost".year IS NOT NULL 
     THEN 
     "lost".year 
    ELSE 
     "won".year 
    END) 
    END   AS "Année", 
    CASE WHEN "open".month IS NOT NULL 
    THEN 
     "open".month 
    ELSE 
    (CASE WHEN "lost".month IS NOT NULL 
     THEN 
     "lost".month 
    ELSE 
     "won".month 
    END) 
    END   AS "Mois", 
    "open".count AS "Ouvertes", 
    "lost".count AS "Perdues", 
    "won".count AS "Gagnées" 
FROM (SELECT 
     year([DOCUMENT_DATE]) AS "year", 
     MONTH([DOCUMENT_DATE]) AS "month", 
     COUNT(*)    AS "count" 
     FROM [MY_TABLE] 
     WHERE [STATUS] < 8 AND [DOCUMENT_DATE] >= ?1 AND [DOCUMENT_DATE] <= ?2 AND ([SEGMENT] = ?3 OR ?3 IS NULL) 
     GROUP BY YEAR([DOCUMENT_DATE]), MONTH([DOCUMENT_DATE])) AS "open" 
    FULL JOIN (SELECT 
       year([DOCUMENT_DATE]) AS "year", 
       MONTH([DOCUMENT_DATE]) AS "month", 
       COUNT(*)    AS "count" 
      FROM [MY_TABLE] 
      WHERE [STATUS] = 8 AND [DOCUMENT_DATE] >= ?1 AND [DOCUMENT_DATE] <= ?2 AND ([SEGMENT] = ?3 OR ?3 IS NULL) 
      GROUP BY YEAR([DOCUMENT_DATE]), MONTH([DOCUMENT_DATE])) AS "lost" 
    ON "open".month = "lost".month AND "open".year = "lost".year 
    FULL JOIN (SELECT 
       year([DOCUMENT_DATE]) AS "year", 
       MONTH([DOCUMENT_DATE]) AS "month", 
       COUNT(*)    AS "count" 
      FROM [MY_TABLE] 
      WHERE [STATUS] > 8 AND [DOCUMENT_DATE] >= ?1 AND [DOCUMENT_DATE] <= ?2 AND ([SEGMENT] = ?3 OR ?3 IS NULL) 
      GROUP BY YEAR([DOCUMENT_DATE]), MONTH([DOCUMENT_DATE])) AS "won" 
    ON "open".month = "won".month AND "open".year = "won".year 
ORDER BY CASE WHEN "open".year IS NOT NULL 
    THEN 
    "open".year 
     ELSE 
      (CASE WHEN "lost".year IS NOT NULL 
      THEN 
       "lost".year 
      ELSE 
       "won".year 
      END) 
     END, 
    CASE WHEN "open".month IS NOT NULL 
    THEN 
     "open".month 
    ELSE 
    (CASE WHEN "lost".month IS NOT NULL 
     THEN 
     "lost".month 
    ELSE 
     "won".month 
    END) 
END 

Я довольно уверен, что есть намного проще и чище способ сделать это, но я не могу понять это.

ответ

5

Я думаю, что это может быть то, что вы ищете, основываясь на описании.

SELECT year([DOCUMENT_DATE]) AS "year", 
     MONTH([DOCUMENT_DATE]) AS "month", 
     COUNT(case when [STATUS] > 8 then 1 end) win_count,  
     COUNT(case when [STATUS] = 8 then 1 end) lost_count, 
     COUNT(case when [STATUS] < 8 then 1 end) open_count 
FROM [MY_TABLE] 
GROUP BY year([DOCUMENT_DATE]),MONTH([DOCUMENT_DATE]) 
ORDER BY 1,2 

Добавить WHERE [DOCUMENT_DATE] >= ?1 AND [DOCUMENT_DATE] <= ?2 AND ([SEGMENT] = ?3 OR ?3 IS NULL) если условие является общим по всем пунктам.

+0

Yup, я был уверен, что есть лучший способ, но не намного лучший способ. Он даже функционально лучше, чем мой, поскольку мои выходы равны нулю, когда нет ничего, а ваш 0 более логичен. Большое спасибо ! – rbntd