MySQL – Listing Rows with WHERE Condition

MySQLmysql-5.5select

I am struggling with a SQL query that lists hosts that are offline.

Problem

The problem occurs when I need to list hosts that don't have any ports open (status = 0), so looking at the table at the bottom it should just list 192.168.1.2, however it lists all of the hosts.

I have tried many queries + sub queries with no luck yet, I would be grateful if you can tell me where I am going wrong and let me know what the correct query is. Thank you.

MariaDB [scanner]> SELECT DISTINCT ports.ip_add FROM ports WHERE ports.status = FALSE;
+-------------+
| ip_add      |
+-------------+
| 192.168.1.1 |
| 192.168.1.2 |
| 192.168.1.3 |
+-------------+

Similar Working Query

This query lists all hosts that have a least one port open (status = 1), great.

MariaDB [scanner]> SELECT DISTINCT ports.ip_add FROM ports WHERE ports.status = TRUE;
+-------------+
| ip_add      |
+-------------+
| 192.168.1.1 |
| 192.168.1.3 |
+-------------+

Table

MariaDB [scanner]> SELECT * FROM ports LIMIT 9;
+--------+-------------+----------+------------+---------------------+
| id     | ip_add      | port     | status     | probe_meta          |
+--------+-------------+----------+------------+---------------------+
|      1 | 192.168.1.1 |       22 |          1 | 2016-03-29 00:01:00 |
|      2 | 192.168.1.1 |       21 |          1 | 2016-03-29 00:02:00 |
|      3 | 192.168.1.1 |       23 |          1 | 2016-03-29 00:03:00 |
|      4 | 192.168.1.2 |       22 |          0 | 2016-03-29 00:05:00 |
|      5 | 192.168.1.2 |       21 |          0 | 2016-03-29 00:06:00 |
|      6 | 192.168.1.2 |       23 |          0 | 2016-03-29 00:07:00 |
|      7 | 192.168.1.3 |       22 |          1 | 2016-03-29 00:09:00 |
|      8 | 192.168.1.3 |       21 |          0 | 2016-03-29 00:10:00 |
|      9 | 192.168.1.3 |       23 |          0 | 2016-03-29 00:11:00 |
+--------+-------------+----------+------------+---------------------+

Best Answer

One other way of doing this would be to aggregate the status column by ip_addr, where the total is equal to zero.

The test-bed:

CREATE TABLE `ports`
(
    `id` INT NOT NULL
    , `ip_add` VARCHAR(15) NOT NULL
    , `port` INT NOT NULL
    , `status` BIT NOT NULL
    , `probe_meta` DATETIME
);

INSERT INTO `ports` 
VALUES (1, '192.168.0.1', 22, 1, '2016-03-21 00:00:00');

INSERT INTO `ports` 
VALUES (1, '192.168.0.2', 22, 0, '2016-03-21 00:01:00');

INSERT INTO `ports` 
VALUES (1, '192.168.0.3', 22, 1, '2016-03-21 00:02:00');

INSERT INTO `ports` 
VALUES (1, '192.168.0.3', 22, 0, '2016-03-21 00:03:00');

The query:

SELECT ip_add
FROM `ports`
GROUP BY ip_add
HAVING SUM(status) = 0;

The results:

enter image description here

SQLFiddle