Здесь вы можете найти отрывок из «Симметричных функций» в книге «Шаблоны проектирования SQL».
Рассмотрим базу данных инвентаря коробок
table Boxes (
length integer,
width integer,
height integer
)
Размеры коробки в реальном мире, однако, обычно не указываются в каком-либо конкретном порядке. Выбор размеров, которые становятся длиной, шириной и высотой, по существу, произвольный. Что если мы хотим идентифицировать коробки в соответствии с их размерами? Например, мы хотели бы иметь возможность сказать, что поле с длинами = 1, шириной = 2 и высотой = 3 совпадает с полем с длинами = 3, шириной = 1 и высотой = 2. Кроме того, как насчет объявления уникального размерного ограничения? Точнее говоря, мы не допустим двух коробок одинакового размера.
Аналитическому уму не составило бы труда признать, что суть проблемы - это порядок столбцов. Значения столбцов длины, ширины и высоты можно поменять местами, чтобы сформировать другую допустимую запись! Поэтому, почему бы нам не ввести 3 псевдостолбца, скажем, A, B и C, таких, что
A ≤ B ≤ C
Тогда единственное ограничение на A, B, C должно удовлетворять нашему требованию! Он может быть реализован как уникальный индекс, основанный на функции, при условии, что мы можем выражать A, B, C аналитически в терминах длины, ширины и высоты. Кусок торта: A - это наибольшая длина, ширина, высота; C является наименьшим из них, но как мы выражаем B? Ну, ответ легко написать
B = least (greatest (length,width),
greatest (width,height),
greatest (height,length) )
хотя это трудно объяснить.
Математическая перспектива, как обычно, многое проясняет. Рассмотрим кубическое уравнение
Если мы знаем корни x1, x2, x3, тогда кубический полином может быть учтен, так что мы имеем
Объединяя оба уравнения, мы выражаем коэффициенты a, b, c через корни x1, x2, x3
Рисунок 4.1: Форма графа многочлена y=(x-x1)(x-x2)(x-x3)
полностью определяется корнями x1, x2 и x3. Обмен ими ни на что не влияет.
Функции -x1-x2-x3, x1x2+x2x3+x3x1, -x1x2x3
симметричны. Перестановка x1, x2, x3 не влияет на значения a, b, c. Другими словами, порядок среди корней кубического уравнения не имеет значения: формально мы говорим о множестве корней, а не о списке корней1. Это именно тот эффект, который мы хотим в нашем примере с Boxes. Симметричные функции, переписанные по длине, ширине, высоте:
length+width+height
length*width+width*height+height*length
length*width*height
Эти выражения были немного упрощены благодаря использованию того факта, что отрицание симметричной функции также симметрично.
Наше последнее решение поразительно похоже на предыдущее, где наибольший оператор играет роль умножения, а наименьший оператор выступает в качестве сложения. Можно даже предложить решение, которое представляет собой сочетание двух
least(length,width,height)
least(length+width,width+height,height+length)
length+width+height
Читатель может проверить, что эти три функции снова симметричны2.
Последний шаг - запись нашего решения в формальном 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
);
Симметричные функции обеспечивают основу для изящного решения. Однако на практике проблему часто можно решить путем перепроектирования схемы. В примере с базой данных инвентаризации ящиков даже не требуется редизайн схемы: нам просто нужно изменить практику вставки неограниченных записей (length,width,height)
и потребовать
length ≥ width ≥ height