带有多个按条件分组的子查询的mysql查询

时间:2018-07-05 05:10:08

标签: mysql sql subquery

嗨,我是MySQL弱的PHP开发人员。中度复杂的查询使我大吃一惊。 下表是vulnerability表。

+-----------------------------------------------------------------------------------------------+ 
| id | webisite_id | low_count| high_count | medium_count | date_time           |   vul_date    |
+-----------------------------------------------------------------------------------------------+
| 20 | 6           | 1        | 1          | 1            | 2018-07-04 09:14:04 | 2018-02-01    |
| 19 | 6           | 30       | 30         | 30           | 2018-07-04 09:13:38 | 2018-01-30    |   
| 18 | 6           | 1        | 1          | 1            | 2018-07-04 09:13:16 | 2018-01-01    |
+-----------------------------------------------------------------------------------------------+  

此表表示数据库中每个网站的低,中,高-漏洞计数。我们可以为每个网站输入尽可能多的条目。但是,与网站唯一相关的条目是每个月的最新条目(基于vul_date)。

在这里我需要帮助,我需要查询来获取最近一年中每个月的每个网站的低,高,中位数的总和,例如,如果->拥有id 1的网站有1、2、3 6月和9月的低,高,中等数量的漏洞  ->与id 2分别为7、8、9的结果应为6月8日,10、12。与上一年的每个月的结果一样。如果没有条目,则应为0。

请注意,条目应为vul_date的最大值,如果站点在同一vul_date上有多个条目,则应获取最新的date_time条目。

我试图尽可能简单地写问题。希望问题得到理解。 请帮助我

谢谢。

2 个答案:

答案 0 :(得分:0)

我认为下面的查询将为您服务。

SELECT 
    SUM(low_count),
    SUM(medium_count),
    SUM(high_count),
    MONTH(vul_date)
FROM
    (SELECT 
        low_count, medium_count, high_count, vul_date, date_time
    FROM
        test
    WHERE
        (website_id , vul_date) IN (SELECT website_id, MAX(vul_date)
            FROM test GROUP BY website_id , MONTH(vul_date))) t
WHERE
    date_time IN (SELECT MAX(date_time) FROM test GROUP BY website_id , vul_date)
GROUP BY MONTH(vul_date);

它的作用是,首先为每个网站ID(即您的最大vul_date)找到最新的进入月份。

SELECT website_id, MAX(vul_date)
            FROM test GROUP BY website_id , MONTH(vul_date)

如果一个vul_date有多个条目,它将使用date_time从中选择最大值。最后,按月分组后,它会汇总所有网站日期。

您可以将上述查询更改为在没有任何网站条目的月份中获得0值。

答案 1 :(得分:0)

DROP TABLE IF EXISTS T;
CREATE TABLE T(id INT, website_id INT, low_count INT, high_count INT, medium_count INT, date_time DATETIME, vul_date DATE);
INSERT INTO T VALUES
( 20 , 6 , 1 , 1 , 1,  '2018-07-04 09:14:04' , '2018-02-01'), 
( 19 , 6 , 30, 30, 30, '2018-07-04 09:13:38' , '2018-01-30'), 
( 18 , 6 , 2 , 2 ,2 ,  '2018-07-04 09:13:16' , '2018-01-01'),
( 17 , 6 , 2 , 2 ,2 ,  '2018-07-04 09:12:01' , '2018-01-01'),
( 90 , 1,1,2,3,'2017-07-05 01:00:00',' 2017-07-06'),
( 90 , 2,8,9,10,'2017-07-05 01:00:00',' 2017-07-06');

select coalesce(c.yyyymm,d.yyyymm) yyyymm,
        coalesce(c.lo,0) lo,
        coalesce(c.hi,0) hi,
        coalesce(c.med,0) med 
from
(

SELECT concat(year(a.vul_date),'-',month(a.vul_date)) yyyymm,
        SUM(LOW_COUNT) lo,SUM(HIGH_COUNT) hi,sum(medium_count) med
from
(
select  website_id,date_time,vul_date
from t
where date_time = (select max(date_time) from t t1 where t1.website_id = t.website_id and t1.vul_date = t.vul_date)
) a
join
(select website_id, date_time,vul_date,
          LOW_COUNT,HIGH_COUNT,medium_count
from t) b
on b.website_id = a.website_id and b.date_time = a.date_time
group by concat(year(a.vul_date),'-',month(a.vul_date))
) c
right join 
(select distinct concat(year(dte),'-',month(dte)) yyyymm from dates d
where dte between date_sub(now(), interval 1 year) and now() 
) d on d.yyyymm = c.yyyymm
;  

子查询a,获取具有最新data_time的vul_date,然后将其自我连接,聚合,然后使用对日期/日历表的正确连接来填充缺少的日期。如果您没有日期/日历,则对于这种运动螺母会很有用,您可以在SO中找到其他选择。

结果

+---------+------+------+------+
| yyyymm  | lo   | hi   | med  |
+---------+------+------+------+
| 2017-7  |    9 |   11 |   13 |
| 2017-8  |    0 |    0 |    0 |
| 2017-9  |    0 |    0 |    0 |
| 2017-10 |    0 |    0 |    0 |
| 2017-11 |    0 |    0 |    0 |
| 2017-12 |    0 |    0 |    0 |
| 2018-1  |   32 |   32 |   32 |
| 2018-2  |    1 |    1 |    1 |
| 2018-3  |    0 |    0 |    0 |
| 2018-4  |    0 |    0 |    0 |
| 2018-5  |    0 |    0 |    0 |
| 2018-6  |    0 |    0 |    0 |
| 2018-7  |    0 |    0 |    0 |
+---------+------+------+------+
13 rows in set (0.04 sec)
相关问题