嗨,我是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
条目。
我试图尽可能简单地写问题。希望问题得到理解。 请帮助我
谢谢。
答案 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)