Here an excerpt from "Symmetric Functions" in "SQL Design patterns" book you may find relevant.
Consider an inventory database of boxes
table Boxes (
length integer,
width integer,
height integer
)
Box dimensions in the real world, however, are generally not given in any specific order. The choice what dimensions becomes length, width, and height is essentially arbitrary. What if we want to identify the boxes according to their dimensions? For example, we would like to be able to tell that the box with length=1, width=2, and height=3 is the same box as the one with length=3, width=1, and height=2. Furthermore, how about declaring a unique dimensional constraint? More specifically, we won’t allow any two boxes that have the same dimensions.
An analytical mind would have no trouble recognizing that the heart of the problem is the column ordering. The values of the length, width, and height columns can be interchanged to form another legitimate record! Therefore, why don’t we introduce 3 pseudo columns, say A, B, and C such that
A ≤ B ≤ C
Then, a unique constraint on A, B, C should satisfy our requirement! It could be implemented as a function based unique index, as long as we can express A, B, C analytically in terms of length, width, height. Piece of cake: A is the greatest of length, width, height; C is the least of them, but how do we express B? Well, the answer is easy to write
B = least (greatest (length,width),
greatest (width,height),
greatest (height,length) )
although difficult to explain.
A mathematical perspective, as usual, clarifies a lot. Consider cubic equation
If we know the roots x1, x2, x3 then, the cubic polynomial could be factored, so that we have
Marrying both equations we express coefficients a, b, c in terms of roots x1, x2, x3
Figure 4.1: A shape of the graph of the polynomial y=(x-x1)(x-x2)(x-x3)
is entirely defined by the roots x1, x2, and x3. Exchanging them doesn’t affect anything.
The functions -x1-x2-x3, x1x2+x2x3+x3x1, -x1x2x3
are symmetric. Permuting x1, x2, x3 has no effect on the values a, b, c. In other words, the order among the roots of cubic equation is irrelevant: formally, we speak of a set of roots, not a list of roots1. This is exactly the effect we want in our example with Boxes. Symmetric functions rewritten in terms of length, width, height are
length+width+height
length*width+width*height+height*length
length*width*height
Those expressions were simplified a little by leveraging the fact that the negation of a symmetric function is also symmetric.
Our last solution is strikingly similar to the earlier one, where the greatest operator plays the role of multiplication, while the least operator goes as addition. It is even possible to suggest a solution, which is a mix-in between the two
least(length,width,height)
least(length+width,width+height,height+length)
length+width+height
A reader can check that these three functions are again symmetric2.
The last step is recording our solution in formal SQL
table Boxes (
length integer,
width integer,
height integer
);
create unique index b_idx on Boxes(
length + width + height,
length * width + width * height + height * length,
length * width * height
);
Symmetric functions provide a basis for a nifty solution. In practice however, a problem can often be solved by schema redesign. In the box inventory database example, we don’t even need schema redesign: we can just require to change the practice of inserting unconstrained records (length,width,height)
, and demand that
length ≥ width ≥ height