You might be familiar with the ALL
option in SQL Server. Perhaps you’ve used it along with the UNION
operator to include any duplicates that might be returned in the result set.
But did you know that ALL
can also be used in two other contexts?
ALL
can be used in the following three contexts:
- As an argument to the
SELECT
clause. - As an argument to the
UNION
clause. - As a logical operator when comparing a scalar value with a single-column set of values.
Examples of each of these contexts follows.
ALL
in the SELECT
Clause
When used with the SELECT
clause, ALL
specifies that duplicate values are returned in the result set.
You probably already use this implicitly without even knowing.
In T-SQL, the syntax for the SELECT
clause goes like this:
SELECT [ ALL | DISTINCT ]
[ TOP ( expression ) [ PERCENT ] [ WITH TIES ] ]
<select_list>
<select_list> ::=
{
*
| { table_name | view_name | table_alias }.*
| {
[ { table_name | view_name | table_alias }. ]
{ column_name | $IDENTITY | $ROWGUID }
| udt_column_name [ { . | :: } { { property_name | field_name }
| method_name ( argument [ ,...n] ) } ]
| expression
[ [ AS ] column_alias ]
}
| column_alias = expression
} [ ,...n ]
The part that goes [ ALL | DISTINCT ]
means that you get a choice between ALL
and DISTINCT
.
The square brackets means that this part is optional.
ALL
specifies that duplicate rows can appear in the result set.DISTINCT
specifies that only unique rows can appear in the result set.
ALL
is the default value, so if you don’t specify ALL
or DISTINCT
, ALL
is used.
Example
So the following two statements are equivalent:
SELECT DogName
FROM Dogs;
SELECT ALL DogName
FROM Dogs;
Example result:
+-----------+ | DogName | |-----------| | Fetch | | Fluffy | | Wag | | Fetch | +-----------+ (4 rows affected) +-----------+ | DogName | |-----------| | Fetch | | Fluffy | | Wag | | Fetch | +-----------+ (4 rows affected)
Both results show that there are two dogs named “Fetch”.
If we swap the ALL
argument for DISTINCT
, only one row will be returned for “Fetch”. This is because DISTINCT
removes any duplicate values from the result set.
SELECT DISTINCT DogName
FROM Dogs;
Example result:
+-----------+ | DogName | |-----------| | Fetch | | Fluffy | | Wag | +-----------+ (3 rows affected)
ALL
in the UNION
Clause
ALL
does the same thing when used with the UNION
clause. It specifies that duplicate values are returned in the result set.
But obviously, UNION
is a different clause to SELECT
, so the context is slightly different.
The UNION
clause concatenates the results of two queries into a single result set. You can use it with or without the ALL
argument:
UNION ALL
– Includes duplicates.UNION
– Excludes duplicates.
Example
Here’s an example of using UNION ALL
to combine two queries.
Let’s add a table called Cats
. So we have two tables: Dogs
and Cats
Dogs
+---------+-----------+ | DogId | DogName | |---------+-----------| | 1 | Fetch | | 2 | Fluffy | | 3 | Wag | | 1002 | Fetch | +---------+-----------+
Cats
+---------+-----------+ | CatId | CatName | |---------+-----------| | 1 | Meow | | 2 | Fluffy | | 3 | Scratch | +---------+-----------+
Now let’s select the dog/cat name from each table and use UNION ALL
to combine the results from both tables.
SELECT DogName AS PetName
FROM Dogs
UNION ALL
SELECT CatName
FROM Cats;
Result:
+-----------+ | PetName | |-----------| | Fetch | | Fluffy | | Wag | | Fetch | | Meow | | Fluffy | | Scratch | +-----------+ (7 rows affected)
In this case, seven rows are returned. We can see that “Fetch” is returned twice. This is because there are two dogs named Fetch.
There’s also a cat and a dog with the same name: Fluffy. (We know the other one’s a cat because there was only one dog called Fluffy in the previous example).
Let’s see what happens when I remove the ALL
argument.
SELECT DogName AS PetName
FROM Dogs
UNION
SELECT CatName
FROM Cats;
Result:
+-----------+ | PetName | |-----------| | Fetch | | Fluffy | | Meow | | Scratch | | Wag | +-----------+ (5 rows affected)
This time only five rows are returned. Both duplicates are removed.
Note that this is different to applying DISTINCT
to each individual SELECT
statement. If we’d done that, Fluffy would have been returned twice, because the ALL
would only apply for the SELECT
statement that it’s being applied against (not to the concatenated results).
Here’s an example to illustrate what I mean.
SELECT DISTINCT DogName AS PetName
FROM Dogs
UNION ALL
SELECT DISTINCT CatName
FROM Cats;
Result:
+-----------+ | PetName | |-----------| | Fetch | | Fluffy | | Wag | | Fluffy | | Meow | | Scratch | +-----------+ (6 rows affected)
The ALL
Operator
The ALL
operator can be used with a subquery to compare a scalar value with a single-column set of values returned by the subquery.
Example
As a refresher, here are our two tables:
Dogs
+---------+-----------+ | DogId | DogName | |---------+-----------| | 1 | Fetch | | 2 | Fluffy | | 3 | Wag | | 1002 | Fetch | +---------+-----------+
Cats
+---------+-----------+ | CatId | CatName | |---------+-----------| | 1 | Meow | | 2 | Fluffy | | 3 | Scratch | +---------+-----------+
Now let’s run a subquery using the ALL
operator.
SELECT
CatId,
CatName
FROM Cats c
WHERE c.CatName = ALL (SELECT DogName FROM Dogs);
Result:
(0 rows affected)
In this case, no rows were returned. This is because ALL
requires the scalar expression to compare positively to every value that is returned by the subquery.
In this case, the subquery was so broad that all rows from the Dogs
table was returned. This would require that each dog had at least one corresponding cat with the same name.
Let’s change the subquery slightly.
SELECT
CatId,
CatName
FROM Cats c
WHERE c.CatName = ALL (
SELECT DogName FROM Dogs
WHERE DogId = 2
);
Result:
+---------+-----------+ | CatId | CatName | |---------+-----------| | 2 | Fluffy | +---------+-----------+
This time I get a positive result, because all rows returned by the subquery had a corresponding row in the Cats
table (in this case, only one row).