10.4. SQL Universal and Existential QualifiersIn SQL, "for all" and "for each" are the universal qualifiers, whereas "there exists" is the existential qualifier. As mentioned in the preceding section, SQL does not have a "for all" predicate; however, logically, the following relationship exists:
which is logically the same as the following:
A "for all" type SQL query is less straightforward than the other queries we have used, because it involves a double-nested, correlated subquery using the NOT EXISTS predicate. The next section shows an example. 10.4.1. Example 1To show a "for all" type SQL query, we will use another table in our Student_course databasea table called Cap (for "capability"). This table has names of students who have multiple foreign-language capabilities. We begin by looking at the table by typing the following query: SELECT * FROM Cap ORDER BY name This query produces the following output (18 rows): NAME LANGU --------- ------- BRENDA FRENCH BRENDA CHINESE BRENDA SPANISH JOE CHINESE KENT CHINESE LUJACK SPANISH LUJACK FRENCH LUJACK GERMAN LUJACK CHINESE MARY JO FRENCH MARY JO GERMAN MARY JO CHINESE MELANIE FRENCH MELANIE CHINESE RICHARD SPANISH RICHARD FRENCH RICHARD CHINESE RICHARD GERMAN (18 row(s) affected) Suppose that we want to find out which languages are spoken by all students (for which we would ask the question, "For each language, does it occur with all students?"). Although this manual exercise would be very difficult for a large table, for our practice table, we can answer the question by displaying and manually counting in the table ordered by language. To see how to answer a question of the type--"Which languages are spoken by all students?"--for a much larger table where sorting and examining the result would be tedious, we will construct a query. After showing the query, we will dissect the result. Following is the query to answer our question: SELECT name, langu FROM Cap x WHERE NOT EXISTS (SELECT 'X' FROM Cap y WHERE NOT EXISTS (SELECT 'X' FROM Cap z WHERE x.langu = z.langu AND y.name = z.name))
This query produces the following output (7 rows): name langu --------- ------- BRENDA CHINESE RICHARD CHINESE LUJACK CHINESE MARY JO CHINESE MELANIE CHINESE JOE CHINESE KENT CHINESE (7 row(s) affected) 10.4.1.1. The way the query worksTo SELECT a "language" spoken by all students, the query proceeds as follows:
These steps are explained in further detail in the next example, in which we use a smaller table, so that the explanation is easier to understand. 10.4.2. Example 2Suppose that we have the simpler table Cap1 (see Table 10-1) when attempting to answer the question "Which languages are spoken by all students?"
The query will be similar to the one used in the previous section: SELECT name, language FROM Cap1 x WHERE NOT EXISTS (SELECT 'X' FROM Cap1 y WHERE NOT EXISTS (SELECT 'X' FROM Cap1 z WHERE x.language = z. language AND y.name = z.name)) ORDER BY language This query produces the following output: name language ------------ ------------ Joe Hindi Mary Hind (2 row(s) affected) 10.4.2.1. The way this query worksThe following is a step-by-step explanation of how this query would work in Table 10-1 (Cap1):
Consider again the "for all" query presented in Example 2: SELECT name, language FROM Cap1 x WHERE NOT EXISTS (SELECT 'X' FROM Cap1 y WHERE NOT EXISTS (SELECT 'X' FROM Cap1 z WHERE x.language = z. language AND y.name = z.name)) ORDER BY language A clue as to what a query of this kind means can be found in the inner query where the outer query is tested. In the phrase that says WHERE x.language = z. language..., the x.language is where the query is testing which language occurs for all names. This query is a SQL realization of a relational division exercise. Relational division is a "for all" operation just like that illustrated earlier. In relational algebra, the query must be set up into a divisor, dividend, and quotient in this pattern:
If the question is "What language for all names?" then the Divisor, A, is names, and the Quotient, B, is language. It is most prudent to set up SQL like relational algebra with a two-column table (like Cap or Cap1) for the Dividend and then treat the Divisor and the Quotient appropriately. Our query will have the column for language, x.language, in the inner query, as language will be the quotient. We have chosen to also report name in the result set. 10.4.3. Example 3Note that the preceding query is completely different from the following query, which asks, "Which students speak all languages?": SELECT DISTINCT name, language FROM Cap1 x WHERE NOT EXISTS (SELECT 'X' FROM Cap1 y WHERE NOT EXISTS (SELECT 'X' FROM Cap1 z WHERE y.language = z.language AND x.name = z.name)) ORDER BY language This query produces the following output: name language ------------ ------------ Mary French Mary Hindi (2 row(s) affected) Note that the inner query contains x.name, which means the question was "Which names occur for all languages?" or, put another way, "Which students speak all languages?" The "all" goes with languages for x.name. ![]() |