简体   繁体   中英

SQL Query returns no rows

I'm working on a query to get a list of all computers that have more than one antivirus installed. Unfortunately I'm unable to get my query to return anything. As you can see in the screenshots below I have setup the data so that it when I get the query working my result set will contain data on devices 1, 2, and 3.

设备表

防病毒产品表

Here is what I've got currently:

SELECT d.ip_address AS "IP Address",
       d.name AS "Computer Name",
       av.name AS "Antivirus Name",
       COUNT(av.deviceID) AS "# of AV Installed"
FROM devices d JOIN anti_virus_products av
ON d.deviceID = av.deviceID
GROUP BY d.ip_address, d.name, av.name
HAVING COUNT(av.deviceID) > 1;

You need to remove the antivirus name av.name from the SELECT and GROUP BY . By including that in the results, the GROUP BY will create a new row for each computer and antivirus name -- because those values create a unique group.

SELECT d.ip_address AS "IP Address",
       d.name AS "Computer Name",
       COUNT(av.deviceID) AS "# of AV Installed"
FROM devices d JOIN anti_virus_products av
ON d.deviceID = av.deviceID
GROUP BY d.ip_address, d.name
HAVING COUNT(av.deviceID) > 1;

Update based on comment to expand query to list names of all AV software installed on the devices:

You could partition the COUNT function. I couldn't find a link to the Oracle documentation for this, but the SQL Server syntax for the OVER Clause seems to work with Oracle. See this example query on SQL Fiddle

SELECT d.ip_address AS "IP Address",
       d.name AS "Computer Name",
       d.deviceid,
       av.name AS "Antivirus Name",
       COUNT(*) OVER (PARTITION BY  d.ip_address, d.name) AS "Total # of AV Installed"
FROM devices d JOIN anti_virus_products av
ON d.deviceID = av.deviceID
GROUP BY d.ip_address, d.name, d.deviceid, av.name;

This example query will return one row for each device and antivirus pair and include the total number of AV installed on the device.

I'm not sure if this will solve your problem, but it provides the additional data you're looking for.

Just remove av.name from the group by clause. Your query returns computers that have a the same anti-virus software installed multiple times -- an unlikely scenario:

SELECT d.ip_address AS "IP Address",
       d.name AS "Computer Name",
       COUNT(av.deviceID) AS "# of AV Installed"
FROM devices d JOIN
     anti_virus_products av
     ON d.deviceID = av.deviceID
GROUP BY d.ip_address, d.name
HAVING COUNT(av.deviceID) > 1;

If you want the names of the antivirus software on a single row, you can use listagg() . Here is the Oracle documentation page for listagg: http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions089.htm#SQLRF30030

As others have said, since there are multiple AV Names per desirged group, the query cannot group by AV Name. This query will return a comma delimited list of AV Names for each computer along with the counts:

SELECT d.ip_address AS "IP Address",
       d.name AS "Computer Name",
       (select name + ',' from anti_virus_products where deviceid = d.deviceid for xml path('')) AS "Antivirus Name",
      avc."# of AV Installed"
FROM devices d
    JOIN (select deviceid,count(*) AS "# of AV Installed" from anti_virus_products
          group by deviceid having count(*) > 1) avc
        ON d.deviceID = avc.deviceID

If you don't need the anti virus name, take it out of your query. If you do, you will need this somewhere in your query. I'll let you figure out where.

and device.deviceid in
(select deviceid
from  
(select deviceid, count(*) records
 from anti_virus_products
 group by device_id
 having count(*) > 1) temp
 )

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