簡體   English   中英

請優化SQL查詢幫助

[英]Optimal SQL query help please

我有兩張桌子:

  • 操作
  • 主機

表格的示例數據如下:

操作

  | ID (bigint) |   ACTION_TIME (datetime)  |   ACTION_NAME (varchar)   |
  -----------------------------------------------------------------------
  |         1   |   2013-08-03 04:42:55     |           test            |
  |         2   |   2013-10-01 06:22:45     |         test56            |
  |         3   |   2013-12-12 08:44:24     |          cloud            |
  |         4   |   2014-01-05 04:20:56     |           demo            |
  |         5   |   2014-03-10 08:20:26     |        console            |
  |         6   |   2014-03-12 05:48:27     |           temp            |

主機

  | ID (bigint) |   ACTION_ID (bigint)  |       DEVICE_ID (bigint) |  CRITICAL_COUNT (bigint)  |  HIGH_COUNT (bigint)   |
  ------------------------------------------------------------------------------------------------------------------------
  |         1   |        1              |                      1   |         200               |            400         |   
  |         2   |        1              |                      2   |         100               |            200         |
  |         3   |        2              |                      1   |         350               |            100         |
  |         4   |        4              |                      3   |           2               |             50         |
  |         5   |        5              |                      2   |           4               |              2         |
  |         6   |        6              |                      2   |          50               |            100         |

我需要使用這些數據來生成折線圖(趨勢)。 我能夠弄清楚如何生成圖形但無法編寫正確的SQL來檢索數據。

說明 :如上表所示,有操作,每個操作涉及主機(一個或多個)。 每個主機都有critical_count,high_count。

現在我想獲得critical_count,high_count(SUM)的月度數據。

**There is one very **important** condition here. If more than one action has same device_id (hosts) in a month, only the latest data (basing on action_time) for that device should be used. The result should include data for last 12 months(including present month). At this month it should be Apr 2013 - Mar 2014**

例如 :對於上述數據,結果應為:

  |     MONTH   |   CRITICAL_COUNT   |  HIGH_COUNT  |
  ---------------------------------------------------
  |         4   |        0           |       0      |
  |         5   |        0           |       0      |
  |         6   |        0           |       0      |
  |         7   |        0           |       0      |
  |         8   |      300           |     600      |
  |         9   |        0           |       0      |
  |        10   |      350           |     100      |
  |        11   |        0           |       0      |
  |        12   |        0           |       0      |
  |         1   |        2           |      50      |
  |         2   |        0           |       0      |
  |         3   |       50           |     100      |

請使用下面的SQL小提琴:

http://sqlfiddle.com/#!2/d179d

謝謝。

我相信這可以做得更好,但MySql似乎沒有窗口功能支持或unpivot運算符。 它也非常難看,因為MySql不允許使用CTE,因此不得不使用嵌套的派生表。 應該注意,我的解決方案假設ACTION_TIME隨ACTION_ID增加。 如果不是這種情況,則必須計算出MAX_ACTION_TIME並加入到MAX_ACTION_ID而不是MAX_ACTION_ID,效率會更低。

Select MONTH,
    Sum(CRITICAL_COUNT) As CRITICAL_COUNT, 
    Sum(HIGH_COUNT) As HIGH_COUNT
From (  
    Select m.ACTION_MONTH As MONTH, 
        Sum(CRITICAL_COUNT) As CRITICAL_COUNT, 
        Sum(HIGH_COUNT) As HIGH_COUNT
    From `hosts` h
        Inner Join `actions` a On h.ACTION_ID = a.ID
        Inner Join (  
            Select DEVICE_ID,
                Month(ACTION_TIME) As ACTION_MONTH, 
                Max(ACTION_ID) As MAX_ACTION_ID -- Max(ACTION_TIME) As MAX_ACTION_TIME
            From `hosts` h
                Inner Join `actions` a On h.ACTION_ID = a.ID
            Group By DEVICE_ID, 
                Month(ACTION_TIME)          
        ) m On m.DEVICE_ID = h.DEVICE_ID
            And m.ACTION_MONTH = Month(a.ACTION_TIME)
            And m.MAX_ACTION_ID = h.ACTION_ID -- And m.MAX_ACTION_TIME = a.ACTION_TIME
    Group By m.ACTION_MONTH

    Union All Select 1,0,0
    Union All Select 2,0,0
    Union All Select 3,0,0
    Union All Select 4,0,0
    Union All Select 5,0,0
    Union All Select 6,0,0
    Union All Select 7,0,0
    Union All Select 8,0,0
    Union All Select 9,0,0
    Union All Select 10,0,0
    Union All Select 11,0,0
    Union All Select 12,0,0
) ALL_MONTHS
Group By MONTH
Order By (Case When MONTH > 3 Then MONTH - 3 Else MONTH + 9 End)

這是工作小提琴:

http://sqlfiddle.com/#!2/d179d/57

查詢是這樣的:

SELECT
m.month,
ifnull(SUM(hosts.critical_count),0) as host_critical,
ifnull(SUM(hosts.high_count),0) as host_high
FROM
(SELECT
MAX(actions.action_time) as maxtime
FROM actions
GROUP BY MONTH(actions.action_time)) a
LEFT OUTER JOIN actions ON a.maxtime = actions.action_time
LEFT OUTER JOIN hosts ON actions.id = hosts.action_id
RIGHT OUTER JOIN 
(SELECT 4 AS MONTH
UNION SELECT 5 AS MONTH
UNION SELECT 6 AS MONTH
UNION SELECT 7 AS MONTH
UNION SELECT 8 AS MONTH
UNION SELECT 9 AS MONTH
UNION SELECT 10 AS MONTH
UNION SELECT 11 AS MONTH
UNION SELECT 12 AS MONTH
UNION SELECT 1 AS MONTH
UNION SELECT 2 AS MONTH
UNION SELECT 3 AS MONTH) m ON m.MONTH = MONTH(a.maxtime)
GROUP BY MONTH(actions.action_time),hosts.action_id,m.month
ORDER BY m.month < 4, m.month;

請注意,我沒有在此代碼中處理多年的情況,因為您希望它在一個會計年度。 如果您也想處理年份部分,可以使用YEAR()並相應地執行。

希望這可以幫助。 祝好運!

select MONTH, CRITICAL_COUNT, HIGH_COUNT from
(
select 
       YEAR(action_time) YEAR, 
       MONTH(action_time) MONTH, 
       SUM(critical_count) CRITICAL_COUNT,
       SUM(high_count) HIGH_COUNT
FROM hosts H1 inner join actions A1 on A1.id = H1.action_id
WHERE DATE_SUB(CURRENT_DATE,INTERVAL 1 YEAR) <= action_time
AND A1.action_time = 
(
  select max(A2.action_time)
  from hosts H2 inner join actions A2 on A2.id = H2.action_id
  where 
  H2.device_id = H1.device_id 
  and MONTH(A2.action_time) = MONTH(A1.action_time)
  and YEAR(A2.action_time) = YEAR(A1.action_time)
)
group by MONTH(action_time), year(action_time)

Union All Select YEAR(DATE_SUB(CURRENT_DATE,INTERVAL 11 MONTH)), MONTH(DATE_SUB(CURRENT_DATE,INTERVAL 11 MONTH)),0,0
Union All Select YEAR(DATE_SUB(CURRENT_DATE,INTERVAL 10 MONTH)), MONTH(DATE_SUB(CURRENT_DATE,INTERVAL 10 MONTH)),0,0
Union All Select YEAR(DATE_SUB(CURRENT_DATE,INTERVAL 9 MONTH)),  MONTH(DATE_SUB(CURRENT_DATE,INTERVAL 9 MONTH)),0,0
Union All Select YEAR(DATE_SUB(CURRENT_DATE,INTERVAL 8 MONTH)),  MONTH(DATE_SUB(CURRENT_DATE,INTERVAL 8 MONTH)),0,0
Union All Select YEAR(DATE_SUB(CURRENT_DATE,INTERVAL 7 MONTH)),  MONTH(DATE_SUB(CURRENT_DATE,INTERVAL 7 MONTH)),0,0
Union All Select YEAR(DATE_SUB(CURRENT_DATE,INTERVAL 6 MONTH)),  MONTH(DATE_SUB(CURRENT_DATE,INTERVAL 6 MONTH)),0,0
Union All Select YEAR(DATE_SUB(CURRENT_DATE,INTERVAL 5 MONTH)),  MONTH(DATE_SUB(CURRENT_DATE,INTERVAL 5 MONTH)),0,0
Union All Select YEAR(DATE_SUB(CURRENT_DATE,INTERVAL 4 MONTH)),  MONTH(DATE_SUB(CURRENT_DATE,INTERVAL 4 MONTH)),0,0
Union All Select YEAR(DATE_SUB(CURRENT_DATE,INTERVAL 3 MONTH)),  MONTH(DATE_SUB(CURRENT_DATE,INTERVAL 3 MONTH)),0,0
Union All Select YEAR(DATE_SUB(CURRENT_DATE,INTERVAL 2 MONTH)),  MONTH(DATE_SUB(CURRENT_DATE,INTERVAL 2 MONTH)),0,0
Union All Select YEAR(DATE_SUB(CURRENT_DATE,INTERVAL 1 MONTH)),  MONTH(DATE_SUB(CURRENT_DATE,INTERVAL 1 MONTH)),0,0
) ALL_MONTHS
where (CRITICAL_COUNT > 0 or HIGH_COUNT> 0)
or (CRITICAL_COUNT = 0 and HIGH_COUNT = 0)
group by YEAR,MONTH
order by YEAR,MONTH

小提琴演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM