3.6 Ranking Regions by Size
3.6.1 Problem
You want to list all regions in the table, and
you want to list them according to their
size. With respect to our example, you wish to list all regions of
two or more containers with a purity of 100, and you wish to sort
that list by the number of containers in each region.
3.6.2 Solution
Use the following query to produce the desired list:
SELECT
p1.ContainerId RegBeg, p2.ContainerId RegEnd,
p2.ContainerId-p1.ContainerId+1 RegionSize
FROM ProductionLine p1, ProductionLine p2
WHERE (p1.ContainerId < p2.ContainerId) AND
NOT EXISTS(SELECT * FROM ProductionLine p3
WHERE (p3.Purity!=100 AND
p3.ContainerId BETWEEN p1.ContainerId AND p2.ContainerId)
OR (p3.ContainerId=p1.ContainerId-1 AND p3.Purity=100)
OR (p3.ContainerId=p2.ContainerId+1 AND p3.Purity=100))
ORDER BY p2.ContainerId-p1.ContainerId DESC
RegBeg RegEnd RegionSize
----------- ----------- -----------
10 12 3
1 2 2
3.6.3 Discussion
As you can see, this query is similar to the one that is used to find
regions. The added feature is the ORDER BY clause, which sorts the
regions according to their size. It relies on the fact that the table
uses an arithmetically increasing index through which the size of a
region can be calculated based on the difference between the two
indices making up the region's borders.
Rather than just report the beginning and ending index for each
region, this query uses the same calculation in the SELECT list as in
the ORDER BY clause to report the size of each region in terms of the
number of containers.
The query comes in handy when you have to prepare data for a
best-fitting algorithm, and you wish to use the database to presort
the data.
You can expand on the solution shown in this recipe, if you like, to
show the smallest available region that is still larger than a given
size. To do this, add a WHERE clause expression to limit the size of
the regions that are sorted. For example:
SELECT TOP 1
p1.ContainerId RegBeg, p2.ContainerId RegEnd,
p2.ContainerId-p1.ContainerId+1 RegionSize
FROM ProductionLine p1, ProductionLine p2
WHERE
(p1.ContainerId < p2.ContainerId) AND
(p2.ContainerId-p1.ContainerId)>=2 AND
NOT EXISTS(SELECT * FROM ProductionLine p3
WHERE (p3.Purity!=100 AND
p3.ContainerId BETWEEN p1.ContainerId AND p2.ContainerId)
OR (p3.ContainerId=p1.ContainerId-1 AND p3.Purity=100)
OR (p3.ContainerId=p2.ContainerId+1 AND p3.Purity=100))
ORDER BY p2.ContainerId-p1.ContainerId ASC
This query returns the smallest possible region that still fits into
the limit. In this case, only the first region that fits the
limitations is returned.
|