Reputation: 879
I have the following problem. suppose I have a table containing an inventory of cars:
VIN, MAKE, MODEL, PRICE
AND I have another table containing various car classes( eg, compact, mid-sized, suv, etc)
MAKE, MODEL, CLASS
JEEP, NULL , SUV
FORD, EXPLORER, SUV
TOYOTA, YARIS, COMPACT
NULL, CUBE, COMPACT
...
I am wondering how can I select all cars in the database of a certain class? Perhaps, I want to know how many cars of each class exists?
I can write a query like this.
SELECT COUNT(*) FROM CARS WHERE (MAKE, MODEL) IN (SELECT MAKE, MODEL FROM CLASSES WHERE CLASS = 'SUV')
The problem here, I wont actually be able to deal with NULLs in my data. I want to say that all models of JEEP are SUVs, or any MAKE car that's called CUBE would be a compact car.
Could this be done assuming there are no conflicts? Can I have a priority set up, like All Porches are CARS except the Cayenne which is an SUV by doing something like this:
MAKE, MODEL, CLASS
PORCHE, NULL , CAR
PORCHE, CAYENNE, SUV
If this isn't possible with MySQL, is there a better DB technology out there that would be good at this. Lets assume that The CLASSES Table would Contain 50K+ Rows and The CARS Table would contain 5M+ Rows. I am looking for a fast way of performing such a query in the database, and not needing to fetch millions of rows to process in a script? Also What if its not just Make and Model, but also sub-model, engine, etc..
Also, I simplified the data quite a bit, there are 4 levels of hierarchy.
Upvotes: 0
Views: 1393
Reputation: 774
Assuming that make and model cannot be both null
for a given class. You can use the ifnull()
function in MySQL:
select cl.class, count(*)
from cars c inner join class cl
on c.make = ifnull(cl.make,c.make)
and c.model=ifnull(cl.model,c.model)
group by cl.class
You may want to add an index on columns makes
and model
for faster access. Since classes
have fewer rows using an inner join (as above) will restrict the number of rows returned.
Upvotes: 1
Reputation: 31308
SELECT s.class, COUNT(*) FROM car c, car_class s WHERE c.make = s.make AND c.model = s.model GROUP BY s.class
should give you something like
SUV 14 COMPACT 32 TRUCK 11 etc.
Upvotes: 0
Reputation: 1270713
You can write your query like this:
SELECT COUNT(*)
FROM CARS c join
classes cl
on (c.make = cl.make or cl.make is null) and
(c.model = cl.model or cl.model is null) and
cl.class = 'SUV'
The problem is that you might get duplicates. So the better count starts with:
select count(distinct c.vin)
. . .
This should work for the two cases you gave, for JEEP and CUBE.
Upvotes: 1