简体   繁体   中英

Mysql: Select specific data from multiple joined tables

I'm having trouble wrapping my brain around this select statement. The data is coming from 3 tables (I've cut out all unnecessary data for easier readability):

mysql> describe vulnerability;
+---------------+------------------+------+-----+---------+----------------+
| Field         | Type             | Null | Key | Default | Extra          |
+---------------+------------------+------+-----+---------+----------------+
| vuln_id       | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| severity      | int(10) unsigned | NO   |     | NULL    |                |
| host_id       | int(10) unsigned | NO   | MUL | NULL    |                |
+---------------+------------------+------+-----+---------+----------------+

mysql> describe cve;
+---------+------------------+------+-----+---------+----------------+
| Field   | Type             | Null | Key | Default | Extra          |
+---------+------------------+------+-----+---------+----------------+
| cve_id  | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| cve     | varchar(15)      | NO   |     | NULL    |                |
| vuln_id | int(10) unsigned | NO   | MUL | NULL    |                |
| year    | int(4) unsigned  | YES  |     | NULL    |                |
+---------+------------------+------+-----+---------+----------------+

mysql> describe host;
+--------------+------------------+------+-----+---------+----------------+
| Field        | Type             | Null | Key | Default | Extra          |
+--------------+------------------+------+-----+---------+----------------+
| host_id      | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| ip_addr      | int(10) unsigned | NO   |     | NULL    |                |
+--------------+------------------+------+-----+---------+----------------+

I want to output the number of hosts that have vulnerabilities that are less than the year 2009 with severity = 3. The year is contained in CVE, which is tied to Vulnerability with the vuln_id FK. The vulnerability has the severity and is tied to Host with the host_id FK. Here is what I have so far:

mysql> select count(distinct ip_addr) from host H 
  inner join vulnerability V on H.host_id = V.host_id 
  inner join CVE C on C.vuln_id = V.vuln_id 
  where V.severity = 3 and C.year < 2009;
+-------------------------+
| count(distinct ip_addr) |
+-------------------------+
|                    5071 |
+-------------------------+

This tells me the total number of hosts with vulnerabilities older than 2009, which is a good start. However, I want to take it a step further and only include those hosts that have 50 or more vulnerabilities. I'm not sure how to do this. Each host entry in the Host table has multiple corresponding Vulnerability entries. I assume I need to add something in my where clause, but I'm stuck.

Thanks in advance. Please let me know if more information is needed.

Try using GROUP BY and HAVING :

SELECT ip_addr
FROM host AS H
INNER JOIN vulnerability AS V
    ON H.host_id = V.host_id
INNER JOIN CVE AS C
    ON C.vuln_id = V.vuln_id
WHERE V.severity = 3 AND C.year < 2009
GROUP BY ip_addr
HAVING COUNT(DISTINCT vuln_id) >= 50

To just get the count wrap the above query inside another query:

SELECT COUNT(*) FROM
(
     SELECT ip_addr
     FROM host AS H
     -- etc... same query as above
) T1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM