Disjoint subtyping is a scenario that is often encountered in data modeling. In one frequently used modeling approach, an entity of a certain type is represented by a database table, and each subtype of this entity is represented by another table. Subtyping is disjoint if an instance of a type corresponds to at most one instance of a subtype.
When querying on a data model with subtypes, a common (verbose?!) way of doing this is using case expressions. The idea of this post is to introduce an alternative to this approach using coalesce. I will be illustrating this across multiple examples.
In the toy schema depicted below, list all orders with their corresponding vendors and customers
Order Table
| Id | Status | Quantity | Type |
|---|---|---|---|
| 1 | 0 | 70000 | 1 |
| 2 | 1 | 80000 | 2 |
| 3 | 0 | 60000 | 2 |
| 4 | 0 | 90000 | 1 |
| 5 | 2 | 69000 | 1 |
| 6 | 1 | 85000 | 1 |
Sale Table
| Id | OrderId | SourceStore | LinkedStore |
|---|---|---|---|
| 1 | 1 | S1 | S2 |
| 2 | 4 | S3 | S5 |
| 3 | 5 | S3 | S6 |
| 4 | 6 | S3 | S1 |
Purchase Table
| Id | OrderId | SourceStore | LinkedStore |
|---|---|---|---|
| 1 | 2 | S2 | S1 |
| 2 | 3 | S3 | S4 |
In this scheme of things, the columns SourceStore and LinkedStore are either vendors or customers in a particular Order depending on the Type of the Order (Purchase or Sale). Fiddle Link
SELECT
O.Id, Status, Quantity, Type,
(CASE
WHEN O.Type = 1 THEN S.SourceStore
ELSE P.LinkedStore
END
) AS Vendor,
(CASE
WHEN O.Type = 1 THEN S.LinkedStore
ELSE P.SourceStore
END
) AS Customer
FROM `ORDER` O
LEFT JOIN `PURCHASE` P ON O.Id = P.OrderId
LEFT JOIN `SALE` S ON O.Id = S.OrderId
SELECT
O.Id, Status, Quantity, Type,
COALESCE(P.LinkedStore, S.SourceStore) AS Vendor,
COALESCE(P.SourceStore, S.LinkedStore) AS Customer
FROM `ORDER` O
LEFT JOIN `PURCHASE` P ON (O.Id = P.OrderId)
LEFT JOIN `SALE` S ON (O.Id = S.OrderId);
Let us look at a more complex, contrived example now. Suppose, for each Order object shown above, there exist Approvals. A Purchase would have a Purchase Approval and a Sale Approval, while a Sale would have a Sale Approval alone. Order_Approval_Mapping maps Orders to Approvals. A Store table has metadata pertaining to the stores.