问题
This is more out of curiosity/scientific interest, than based on a real problem and I once asked my databases lecturer about this, but he could not answer/understand my question. So I decided to come over here.
A programming language is supposed to be a tool and tools are made to make working easier, right? So why is it that you can find all entries in a one table by simply doing SELECT * FROM foo WHERE bar=42;
. But as soon as there are multiple tables involved, there is no easy/intuitive way to say "find all tuple meeting this criteria"?
The given example in the script is something like this (this is translated from German, so the naming might be a bit confusing):
For Table of the folowing format:
- component(CNR,Cname,Color,Weight,City)
- project(PNR,Pname,City)
- scp(SNR,CNR,PNR,Quantity)
Primary keys in bold. The example is about components which are shipped to different projects in different cities.
The task is to write a query to find all components that are/were shipped to all projects in one specific city.
The given solution looks like this:
SELECT CNR
FROM components
WHERE NOT EXISTS ( SELECT 1
FROM project
WHERE project.city = 'Foobar Town'
AND NOT EXISTS ( SELECT 1
FROM scp
WHERE scp.PNR = projekt.PNR
AND scp.CNR = components.CNR ));
I mean yes it is correct, makes sense and even works. But it is not intuitive and certainly does not make life easier! So where is the reason for this I wonder? Since we were told that it is crucial for the exams, that we are able to write such queries I there is no way around learning it.
I haven't been able to find a simpler solution to this yet. Neither by googling nor trying by myself. There must be a better reason to this than "everybody is too lazy to fix this". Any one any ideas?
The example and all the material given to the students in our course is based on SQL92.
Thank you for your answers
回答1:
Your question is: "Find all components that are/were shipped to all projects in one specific city." You are rephrasing this as "Find all components where there is no project in a given city that doesn't have the component."
I'd be more inclined to answer this directly:
select scp.component
from scp join
projects p
on scp.pnr = p.pnr
where p.city = 'Foobar Town'
group scp.component
having count(distinct scp.pnr) = (select count(distinct pnr)
from projects
where city = 'Foobar Town'
);
This counts the number of distinct projects in the city and compares them to the number of projects in the city (the distinct
id probably not necessary in the subquery.
First, I'm not sure if this is simpler. Second, I'm the first to admit that the NOT EXISTS
method may be more efficient, although the nesting of NOT EXISTS
in subqueries may be detrimental to performance. I do, however, think that this is easier to follow.
来源:https://stackoverflow.com/questions/27722404/why-are-double-nested-not-exists-statements-unavoidable-in-sql