I am trying to merge one table on another table based on a given value. But, it isn't as simple as a JOIN. ( I found plenty of JOIN examples online, but none like this. Also, I am not incredibly great at DB queries. )
For a simple example of what I am trying to accomplish, lets say I run a computer shop and sell multiple computers to multiple people. For whatever reason, these machines periodically check-in with me, and I want to know which customers of mine have a machine that is currently offline. However, if they have at least 1 machine online, I DO NOT want to see ANY of the machines they have that are either online OR offline.
My query so far is something like this:
SELECT *
FROM Computers
LEFT JOIN Computers_On_Customers ON Computer_ID = Computers.ID
LEFT JOIN Customers ON Computers_On_Customers.Customer_ID = Customers.ID
WHERE Computers.Currently_Online LIKE "0"
However, if a Customer has 2 computers, one of each status, it will show 1 computer, when I want it to show neither. (Because one is currently offline, and therefore I do not care about the online one.) How could I go about this?
Here is a rough visual approximation of my database:
Customers:
ID Other Stuff
Computers_On_Customers
ID Customer_ID Computer_ID
Computers:
ID Currently_Online
Any help would be greatly appreciated.
You could use NOT EXISTS to filter out computers whose owners have a computer online:
SELECT * FROM Computers
LEFT JOIN Computers_On_Customers ON Computer_ID = Computers.ID
LEFT JOIN Customers ON Computers_On_Customers.Customer_ID = Customers.ID
WHERE
Computers.Currently_Online LIKE "0" AND
NOT EXISTS (
SELECT 1 FROM Computers_On_Customers
LEFT JOIN Computers ON Computer_ID = Computers.ID
WHERE
Currently_Online LIKE "1" AND
Computers_On_Customers.Customer_ID = Customers.ID
)
You need to perform an aggregation and then take the result of that aggregation and select with the filters you want.
Using your example. Take the where and move it outside an aggregation selection.
SELECT
ID, offline_count
from
(SELECT
Customers.ID,
SUM(IF(Computers.Currently_Online Like '0', 0, 1)) 'offline_count'
FROM
Computers
LEFT JOIN Computers_On_Customers ON Computer_ID = Computers.ID
LEFT JOIN Customers ON Computers_On_Customers.Customer_ID = Customers.ID
GROUP BY Customers.ID) c
where
c.offline_count > 0
Assuming data_table has information to specify if a user is online or offline and there can be multiple entries. Aggregate the users and do sum of the offline count, if its > 0 after aggregating then you know that user has an offline entry. You can achieve similar with HAVING clause.
Assuming you just want the Customer data - surely you can just roll the whole thing up with a GROUP BY
clause ... and since you're only after records where the maximum value of Computers.Currently_Online = 0
you should be able to use a MAX
function to exclude anything where that value > 0.
SELECT Customers.*, MAX(Computers.Currently_Online) AS computer_online
FROM Customers
INNER JOIN Computers_On_Customers
ON Customers.ID = Computers_On_Customers.Customer_ID
INNER JOIN Computers
ON Computers_On_Customers.Computer_ID = Computers.ID
GROUP BY Customers.ID
HAVING computer_online = 0
Personally I don't like nesting SELECTs unless I absolutely have to ... and in those instances I'd prefer to put it into a stored procedure.
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.