I'm getting myself tied up in knots over this one, so hopefully, someone can help.
I need to create a view table and join 2 tables together, but I only need to display entries with missing data.
So, I have a table that lists drones I own, including the manufacturer, serial number and the date purchased, and I have another table that lists maintenance data, including the type of maintenance each device received. This table also includes similar data to the first table.
I need to pull the device data from the first table and compare that to the maintenance table and display the drones that have not received a particular type of maintenance.
This is what I have tried
CREATE VIEW uncommissioned AS
SELECT DISTINCT
drone.manufacturer AS manufacture,
drone.serial,
drone.type,
drone.purchase_date,
maintenance.type AS maintenance
FROM drone
INNER JOIN maintenance ON drone.type = maintenance.type
WHERE maintenance.type = 'NULL';
But this gives an empty table, any suggestions on where I'm going wrong?
I think that you want an anti- LEFT JOIN
:
CREATE VIEW uncommissioned AS
SELECT DISTINCT
d.manufacturer AS manufacture,
d.serial,
d.type,
d.purchase_date,
d.type AS maintenance
FROM drone d
LEFT JOIN maintenance m ON d.type = m.type
WHERE m.type IS NULL;
Notes:
to chek for nullity, you need the IS NULL
construct (your code checks for litteral string 'NULL'
):
if you want to display the maintenance type, you need to take that information from the drone
table rather than from the maintenance
table
You could also phrase this with a NOT EXISTS
condition and a correlated subquery:
CREATE VIEW uncommissioned AS
SELECT DISTINCT
d.manufacturer AS manufacture,
d.serial,
d.type,
d.purchase_date,
d.type AS maintenance
FROM drone d
WHERE NOT EXISTS (SELECT 1 FROM maintenance m WHERE d.type = m.type)
IS NULL is right, and RIGHT JOIN because NULL in right table maintance
Try it: SELECT DISTINCT drone.manufacturer AS manufacture, drone.serial, drone.type, drone.purchase_date, maintenance.type AS maintenance FROM drone RIGHT OUTER JOIN maintenance ON drone.type = maintenance.type WHERE maintenance.type IS NULL;
Based on your last comment:
Taking it step-by-step and building up what you want to do (we'll combine these sets later) ....
You're looking to check out all of your drones. So let's select columns from drones
table to see what's there.
SELECT * FROM drones ;
\nmanufacturer | serial | type | purchase_date \n:--------------------- | -----: | ---: | :------------------ \nLockheed Martin | 1 | 1 | 2020-01-01 00:00:00 \nAerial Robotic Systems | 2 | 10 | 2020-02-01 00:00:00 \nAmazon | 3 | 100 | 2020-03-01 00:00:00 \nNorthrup Grumman | 4 | 2 | 2020-04-01 00:00:00 \nDJI | 5 | 20 | 2020-05-01 00:00:00 \nTitan Aerospace | 6 | 200 | 2020-06-01 00:00:00 \n
What's in the maintenance
table?
SELECT * FROM maintenance ;
\ndronetype | mxtype \n--------: | :---------------- \n 1 | Replace propeller\n 1 | Commissioned \n 100 | Commissioned \n 2 | Commissioned \n 20 | Commissioned \n 200 | DECOMMISSIONED \n
How do these two tables relate together? Let's hook them together with a JOIN
on type
. MOTE: I made an assumption and changed maintenance.type
to be more descriptive of how I think these relations should be.
3.1. Which JOIN
do we need? ( For an illustration: https://www.edureka.co/blog/sql-joins-types ). I'll only look at INNER
and OUTER
JOIN
s.
3.1.1 An INNER JOIN
will only give us records that match in BOTH tables.
SELECT d.manufacturer, d.serial, d.type, d.purchase_date, m.mxtype FROM drones d INNER JOIN maintenance m ON d.type = m.dronetype ;
\nmanufacturer | serial | type | purchase_date | mxtype \n:--------------- | -----: | ---: | :------------------ | :---------------- \nLockheed Martin | 1 | 1 | 2020-01-01 00:00:00 | Replace propeller\nLockheed Martin | 1 | 1 | 2020-01-01 00:00:00 | Commissioned \nAmazon | 3 | 100 | 2020-03-01 00:00:00 | Commissioned \nNorthrup Grumman | 4 | 2 | 2020-04-01 00:00:00 | Commissioned \nDJI | 5 | 20 | 2020-05-01 00:00:00 | Commissioned \nTitan Aerospace | 6 | 200 | 2020-06-01 00:00:00 | DECOMMISSIONED \n
That's not really what we want.
3.1.2 An OUTER JOIN
will give us records from one of the tables and the rows that match in the other table. Unmatched rows will be NULL
.
SELECT d.manufacturer, d.serial, d.type, d.purchase_date, m.mxtype FROM drones d LEFT OUTER JOIN maintenance m ON d.type = m.dronetype ;
\nmanufacturer | serial | type | purchase_date | mxtype \n:--------------------- | -----: | ---: | :------------------ | :---------------- \nLockheed Martin | 1 | 1 | 2020-01-01 00:00:00 | Replace propeller\nLockheed Martin | 1 | 1 | 2020-01-01 00:00:00 | Commissioned \nAmazon | 3 | 100 | 2020-03-01 00:00:00 | Commissioned \nNorthrup Grumman | 4 | 2 | 2020-04-01 00:00:00 | Commissioned \nDJI | 5 | 20 | 2020-05-01 00:00:00 | Commissioned \nTitan Aerospace | 6 | 200 | 2020-06-01 00:00:00 | DECOMMISSIONED \nAerial Robotic Systems | 2 | 10 | 2020-02-01 00:00:00 | null \n
That shows us all of the `drones` with a `NULL` record for the non-matched one.
But we want to show drones that haven't been Commissioned
yet in the maintenance
table.
SELECT d.manufacturer, d.serial, d.type, d.purchase_date, m.mxtype FROM drones d LEFT OUTER JOIN maintenance m ON d.type = m.dronetype WHERE m.mxtype <> 'commissioned' ;
\nmanufacturer | serial | type | purchase_date | mxtype \n:-------------- | -----: | ---: | :------------------ | :---------------- \nLockheed Martin | 1 | 1 | 2020-01-01 00:00:00 | Replace propeller\nTitan Aerospace | 6 | 200 | 2020-06-01 00:00:00 | DECOMMISSIONED \n
But now we're missing our unmatched record, and we're showing records we don't want (like the Lockheed Martin
record, which has 2 maintenance
records with one being Commissioned
).
So let's choose records from our drones
table that don't have a Commissioned
record in maintenance
. We can do that with a NOT EXISTS
.
SELECT d.manufacturer, d.serial, d.type, d.purchase_date FROM drones d WHERE NOT EXISTS ( SELECT 1 /* This can be anything. It's ignored. */ FROM maintenance m WHERE m.mxtype = 'commissioned' AND m.dronetype = d.type ) ;
\nmanufacturer | serial | type | purchase_date \n:--------------------- | -----: | ---: | :------------------ \nAerial Robotic Systems | 2 | 10 | 2020-02-01 00:00:00 \nTitan Aerospace | 6 | 200 | 2020-06-01 00:00:00 \n
Now we've got the two drones that don't have a record in maintenance
for being Commissioned
.
NOTE: In this final query, we used a correlated subquery to link the maintenance
table to the drones
table, and we included a condition on our query for the maintenance
table to only select records with mxtype
or commissioned
. And the WHERE NOT EXISTS
will filter the query of the drones
table to exclude any rows that DO have a match in the subquery.
You can play with the query and data here: db<>fiddle
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.