Classification Table - Part 2

In a recent post I wrote about a flexible structure used for storing and retrieving classifications form a database. My example retrieved “entities” for a single classification, and those entities that matched any of that classifications children.

In this entry I want to expand on this approach, and demonstrate how results can be limited to only those entities that match a specific list of classifications.

Id ParentId Name
1 1 Attributes
2 2 Color
3 2 Red
4 2 Blue
5 2 Green
6 2 Purple
7 1 Font
8 7 Times New Roman
9 8 Bold
10 8 Italic
11 7 Arial
12 11 Bold
13 7 Calibri
14 13 Bold

ClassificationId EntityId
4 1
9 1
4 2
10 2


Using the tables above, let retrieve all entities that are related to ClassificationId 9 (Times New Roman – Bold) AND ClassificationId 4 (Blue).

At first glance I thought this was pretty simple and used the IN clause to match my list of classification ids.

1
2
3
4
SELECT * FROM Entity 
LEFT JOIN EntryClassification 
ON Entity.Id = EntryClassification.EntityId 
WHERE EntryClassification.ClassificationId in (9,4)

Unfortunately this approach fails to return the correct result set.  Instead of retrieving those entities that are related to BOTH classifications, the IN clause determines whether a specified value matches ANY value in the list. 

After quite a few experimentations , here is the solution I came up with.

1
2
3
4
5
SELECT * FROM Entity WHERE Entity.Id in 
(SELECT ec.EntityId FROM EntityClassification ec
WHERE ec.ClassificationId in (9,4) 
GROUP BY ec.EntryId 
HAVING Count(ec.EntryId) = 2))

If the number of items in your list will change, then you will need to either pass in the number of items or calculate the total by examining the string of Ids.  If you always know the delimiter, the following is an interesting hack to determine the number of items.

1
2
3
DECLARE @ClassificationIds varchar(10) = '9,4'
DECLARE @Count int
SET @Count = (LEN(@ClassificationIds ) - LEN(REPLACE(@ClassificationIds , ',', ''))+1)


No Comments so far >>



Leave a comment

(required)

(required)