Привет, я слабый PHP-разработчик в MySQL. Сложные сложные запросы заставляют мою голову стрелять. Ниже приведена 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, низкий, высокий, средний номер уязвимости, в июне месяце и → то, что с id
2 имеет 7, 8, 9 соответственно, результат должен быть 8 июня 10, 12. И, как и последний год, каждый месяц должен быть получен результат. Если ни одна запись не должна быть 0.
Обратите внимание, что записи должны быть максимальным значением vul_date
и если сайт имеет несколько записей на одном и том же vul_date
получите последнюю date_time
.
Я постарался написать вопрос так же просто. надеюсь, что вопрос будет понят. Пожалуйста помоги мне с этим
Заранее спасибо.
Я думаю, что ниже запрос будет работать для вас.
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);
То, что он делает, сначала находит последний месяц входа в мудрый для каждого идентификатора сайта, который является вашим max vul_date.
SELECT website_id, MAX(vul_date)
FROM test GROUP BY website_id , MONTH(vul_date)
Если для vul_date имеется более одной записи, она использует date_time для выбора максимального значения из них. Наконец, он суммирует всю дату веб-сайта после группировки месяца.
Вы можете изменить указанный выше запрос, чтобы получить значение 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
;
Sub query a get the vul_date с самым последним значением data_time, которое затем присоединяется, агрегируется, а затем заполняется отсутствующими датами, используя правильное соединение с таблицей даты/календаря. Если у вас нет дат/календаря, это было бы полезно для этого вида упражнений, есть альтернативы, которые вы можете найти в 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)