Ответ 1
Вы указываете
Как я могу написать запрос, который может выбрать все заказы, которые по крайней мере 85% похоже на определенный порядок?
Это важное упрощение по сравнению с "всеми парами заказов" которые по меньшей мере на 85% похожи друг на друга ".
Мы будем использовать TDQD (Test-Driven Query Design) и некоторый анализ, чтобы помочь нам.
Отборочные
Чтобы быть удаленно похожими, два заказа должны иметь по крайней мере один элемент в общий. Этот запрос может быть использован для определения того, какие заказы имеют по крайней мере один элемент вместе с указанным порядком:
SELECT DISTINCT I1.OrderID AS ID
FROM OrderItem AS I1
JOIN OrderItem AS I2 ON I2.ItemID = I1.ItemID AND I2.OrderID = <specified order ID>
WHERE I1.OrderID != <specified order ID>
Это сокращает список других заказов, которые нужно изучить довольно много, хотя если указанный заказ включает один из ваших самых популярных товаров, это вероятно, что многие другие заказы также сделали это.
Вместо DISTINCT вы можете использовать:
SELECT I1.OrderID AS ID, COUNT(*) AS Num_Common
FROM OrderItem AS I1
JOIN OrderItem AS I2 ON I2.ItemID = I1.ItemID AND I2.OrderID = <specified order ID>
WHERE I1.OrderID != <specified order ID>
GROUP BY I1.OrderID
Это дает вам количество элементов в том порядке, в котором оно имеет общее с указанным порядком. Нам также нужно количество предметов в каждом порядок:
SELECT OrderID AS ID, COUNT(*) AS Num_Total
FROM OrderItem
GROUP BY OrderID;
Идентичные заказы
Для 100% сходства два заказа будут иметь как можно больше элементов так как у каждого есть предметы. Это, вероятно, не найдет много пар заказов, хоть. Мы можем найти заказы с точно такими же элементами, как и заданный порядок достаточно легко:
SELECT L1.ID
FROM (SELECT OrderID AS ID, COUNT(*) AS Num_Total
FROM OrderItem
GROUP BY OrderID
) AS L1
JOIN (SELECT I1.OrderID AS ID, COUNT(*) AS Num_Common
FROM OrderItem AS I1
JOIN OrderItem AS I2 ON I2.ItemID = I1.ItemID AND I2.OrderID = <specified order ID>
WHERE I1.OrderID != <specified order ID>
GROUP BY I1.OrderID
) AS L2 ON L1.ID = L2.ID AND L1.Num_Total = L2.Num_Common;
Изменить: это оказывается недостаточно строгим; для того, чтобы заказы были идентичными, количество элементов в указанном порядке также должно быть таким же, как общее число:
SELECT L1.ID, L1.Num_Total, L2.ID, L2.Num_Common, L3.ID, L3.Num_Total
FROM (SELECT OrderID AS ID, COUNT(*) AS Num_Total
FROM OrderItem
GROUP BY OrderID
) AS L1
JOIN (SELECT I1.OrderID AS ID, COUNT(*) AS Num_Common
FROM OrderItem AS I1
JOIN OrderItem AS I2 ON I2.ItemID = I1.ItemID AND I2.OrderID = <specified order ID>
WHERE I1.OrderID != <specified order ID>
GROUP BY I1.OrderID
) AS L2 ON L1.ID = L2.ID AND L1.Num_Total = L2.Num_Common
JOIN (SELECT OrderID AS ID, COUNT(*) AS Num_Total
FROM OrderItem
WHERE OrderID = <specified order ID>
GROUP BY OrderID
) AS L3 ON L2.Num_Common = L3.Num_Total;
Похожие заказы - анализ формулы
Применение сходство с Jaccard как определено в Википедии, двум заказам A и B, с | A | считая числа элементов в порядке A, сходство Jaccard J (A, B) = | A∩B | ÷ | A∪B |, где | A∩B | это количество общих для два заказа и | A∪B | это общее количество разных предметов прописал.
Чтобы выполнить критерий подобия 85% Jaccard, если количество элементов в либо порядок меньше некоторого порога, заказы должны быть одинаковыми. Например, если оба заказа A и B имеют 5 элементов, скажем, но там один элемент, отличный от двух, он дает вам 4 общих элемента (| A∩B |) и всего 6 предметов (| A∪B |), поэтому сходство Jaccard J (A, B) 66⅔%.
Для 85% подобия, когда в каждом из двух ордеров есть N элементов 1 элемент отличается, (N-1) ÷ (N + 1) ≥ 0,85, что означает N > 12 (Точнее, 12). Для доли F = J (A, B) один элемент отличается означает (N-1) ÷ (N + 1) ≥ F, который можно решить для N, что дает N ≥ (1 + F) ÷ (1 - F). Поскольку требование подобия возрастает, заказы должны быть одинаковыми для все больших значений N.
Обобщая еще больше, допустим, что мы имеем разные порядки размера с элементами N и M (без ограничения общности, N < M). Максимум значение | A∩B | теперь N и минимальное значение | A∪B | есть M (что означает все предметы в меньшем порядке отображаются в большем порядке). Давайте определите, что M = N + Δ, и что есть ∂ элементы, присутствующие в меньший порядок, который отсутствует в большем порядке. Следует, что есть Δ + ∂ элементы, присутствующие в большем порядке, которые не находятся в меньшего порядка.
По определению, тогда | A∩B | = N-∂, и | A∪B | = (N-∂) + ∂ + (N + Δ- (N-∂)), где три добавленных члена представляют (1) число общие предметы между двумя заказами, (2) количество предметов только в меньший порядок и (3) количество предметов только в большем порядке. Это упрощает: | A∪B | = N + Δ + ∂.
Уравнение ключа
Для фракции подобия F нас интересуют пары ордеров, где J (A, B) ≥ F, поэтому:
(N-∂) ÷ (N + Δ + ∂) ≥ F
F ≤ (N-∂) ÷ (N + Δ + ∂)
Мы можем использовать электронную таблицу, чтобы отобразить взаимосвязь между ними. Для заданное количество элементов в меньшем порядке (ось х) и для заданного подобия, мы можем построить максимальное значение ∂, которое дает нам сходство F. Формула:
∂ = (N (1-F) - FΔ) ÷ (1 + F)
Это линейное уравнение в N и Δ для постоянной F; он нелинейный для разных значений F. Ясно, что ∂ должно быть неотрицательным целое число.
Учитывая F = 0,85, для заказов, которые имеют одинаковый размер (Δ = 0), для 1 ≤ N < 13, ∂ = 0; для 13≤N < 25, ≤ ≤ 1; для 25 ≤ N < 37, ≤ ≤ 2, для 37 ≤ N < 50, ∂ ≤ 3.
Для заказов, которые отличаются на 1 (Δ = 1), для 1 ≤ N < 18, ∂ = 0; за 18 ≤ N < 31, ∂ ≤ 1; для 31 ≤ N < 43, ≤ ≤ 2; и т.д. Если Δ = 6, вы нужно N = 47 до того, как заказы по-прежнему остаются на 85% похожими на ∂ = 1. Что означает, что у небольшого заказа есть 47 предметов, из которых 46 являются общими с большой порядок из 53 предметов.
Аналогичные заказы - применение анализа
До сих пор так хорошо. Как мы можем применить эту теорию к выбору заказов аналогично указанному порядку?
Сначала отметим, что указанный порядок может быть того же размера, что и аналогичный порядок, или больше, или меньше. Это немного усложняет ситуацию.
Параметры вышеуказанного уравнения:
- N - количество элементов в меньшем порядке
- Δ - разница между количеством элементов в большем порядке и N
- F - исправлено
- ∂ - количество элементов в меньшем порядке, не соответствующих более крупному заказу
Значения, доступные с использованием незначительных вариаций в запросах, разработанных в верхней части:
- NC - количество общих элементов
- NA - количество элементов в указанном порядке
- NB - количество элементов в сравниваемом порядке
Соответствующие запросы:
SELECT OrderID AS ID, COUNT(*) AS NA
FROM OrderItem
WHERE OrderID = <specified order ID>
GROUP BY OrderID;
SELECT OrderID AS ID, COUNT(*) AS NB
FROM OrderItem
WHERE OrderID != <specified order ID>
GROUP BY OrderID;
SELECT I1.OrderID AS ID, COUNT(*) AS NC
FROM OrderItem AS I1
JOIN OrderItem AS I2 ON I2.ItemID = I1.ItemID AND I2.OrderID = <specified order ID>
WHERE I1.OrderID != <specified order ID>
GROUP BY I1.OrderID
Для удобства мы хотим получить значения N и N + Δ (и, следовательно, Δ), поэтому мы можем использовать СОЮЗ, чтобы упорядочить вещи соответствующим образом:
- NS = N - количество элементов в меньшем порядке
- NL = N + Δ - количество элементов в большем порядке
а во второй версии запроса UNION:
- NC = N - ∂ - общее количество элементов
Оба запроса содержат два идентификатора заказа, чтобы вы могли отслеживать остальная часть информации о заказе позже.
SELECT v1.ID AS OrderID_1, v1.NA AS NS, v2.ID AS OrderID_2, v2.NB AS NL
FROM (SELECT OrderID AS ID, COUNT(*) AS NA
FROM OrderItem
WHERE OrderID = <specified order ID>
GROUP BY OrderID
) AS v1
JOIN (SELECT OrderID AS ID, COUNT(*) AS NB
FROM OrderItem
WHERE OrderID != <specified order ID>
GROUP BY OrderID
) AS v2
ON v1.NA <= v2.NB
UNION
SELECT v2.ID AS OrderID_1, v2.NB AS NS, v1.ID AS OrderID_2, v1.NA AS NL
FROM (SELECT OrderID AS ID, COUNT(*) AS NA
FROM OrderItem
WHERE OrderID = <specified order ID>
GROUP BY OrderID
) AS v1
JOIN (SELECT OrderID AS ID, COUNT(*) AS NB
FROM OrderItem
WHERE OrderID != <specified order ID>
GROUP BY OrderID
) AS v2
ON v1.NA > v2.NB
Это дает нам табличное выражение с столбцами OrderID_1, NS, OrderID_2, NL, где NS - количество элементов в "меньшем порядке", а NL - количество элементов в большем порядке. Поскольку в номера заказов, генерируемые табличными выражениями v1 и v2, нет нужно беспокоиться о "рефлексивных" записях, где значения OrderID являются одна и та же. Добавление NC к этому наиболее легко обрабатывается в запросе UNION:
SELECT v1.ID AS OrderID_1, v1.NA AS NS, v2.ID AS OrderID_2, v2.NB AS NL, v3.NC AS NC
FROM (SELECT OrderID AS ID, COUNT(*) AS NA
FROM OrderItem
WHERE OrderID = <specified order ID>
GROUP BY OrderID
) AS v1
JOIN (SELECT OrderID AS ID, COUNT(*) AS NB
FROM OrderItem
WHERE OrderID != <specified order ID>
GROUP BY OrderID
) AS v2
ON v1.NA <= v2.NB
JOIN (SELECT I1.OrderID AS ID, COUNT(*) AS NC
FROM OrderItem AS I1
JOIN OrderItem AS I2 ON I2.ItemID = I1.ItemID AND I2.OrderID = <specified order ID>
WHERE I1.OrderID != <specified order ID>
GROUP BY I1.OrderID
) AS v3
ON v3.ID = v2.ID
UNION
SELECT v2.ID AS OrderID_1, v2.NB AS NS, v1.ID AS OrderID_2, v1.NA AS NL, v3.NC AS NC
FROM (SELECT OrderID AS ID, COUNT(*) AS NA
FROM OrderItem
WHERE OrderID = <specified order ID>
GROUP BY OrderID
) AS v1
JOIN (SELECT OrderID AS ID, COUNT(*) AS NB
FROM OrderItem
WHERE OrderID != <specified order ID>
GROUP BY OrderID
) AS v2
ON v1.NA > v2.NB
JOIN (SELECT I1.OrderID AS ID, COUNT(*) AS NC
FROM OrderItem AS I1
JOIN OrderItem AS I2 ON I2.ItemID = I1.ItemID AND I2.OrderID = <specified order ID>
WHERE I1.OrderID != <specified order ID>
GROUP BY I1.OrderID
) AS v3
ON v3.ID = v1.ID
Это дает нам табличное выражение с столбцами OrderID_1, NS, OrderID_2, NL, NC, где NS - количество элементов в "меньшем порядке", а NL - количество элементов в более крупном заказе, а NC - количество элементов в общем.
Учитывая NS, NL, NC, мы ищем заказы, которые удовлетворяют:
(N-∂) ÷ (N + Δ + ∂) ≥ F.
- N - количество элементов в меньшем порядке
- Δ - разница между количеством элементов в большем порядке и N
- F - исправлено
-
∂ - количество элементов в меньшем порядке, не соответствующих более крупному заказу
-
NS = N - количество элементов в меньшем порядке
- NL = N + Δ - количество элементов в большем порядке
- NC = N - ∂ - общее количество элементов
Следовательно, условие должно быть:
NC / (NL + (NS - NC)) ≥ F
Термин LHS должен оцениваться как число с плавающей запятой, а не как целочисленное выражение. Применив это к запросу UNION выше, вы получите:
SELECT OrderID_1, NS, OrderID_2, NL, NC,
CAST(NC AS NUMERIC) / CAST(NL + NS - NC AS NUMERIC) AS Similarity
FROM (SELECT v1.ID AS OrderID_1, v1.NA AS NS, v2.ID AS OrderID_2, v2.NB AS NL, v3.NC AS NC
FROM (SELECT OrderID AS ID, COUNT(*) AS NA
FROM OrderItem
WHERE OrderID = <specified order ID>
GROUP BY OrderID
) AS v1
JOIN (SELECT OrderID AS ID, COUNT(*) AS NB
FROM OrderItem
WHERE OrderID != <specified order ID>
GROUP BY OrderID
) AS v2
ON v1.NA <= v2.NB
JOIN (SELECT I1.OrderID AS ID, COUNT(*) AS NC
FROM OrderItem AS I1
JOIN OrderItem AS I2 ON I2.ItemID = I1.ItemID AND I2.OrderID = <specified order ID>
WHERE I1.OrderID != <specified order ID>
GROUP BY I1.OrderID
) AS v3
ON v3.ID = v2.ID
UNION
SELECT v2.ID AS OrderID_1, v2.NB AS NS, v1.ID AS OrderID_2, v1.NA AS NL, v3.NC AS NC
FROM (SELECT OrderID AS ID, COUNT(*) AS NA
FROM OrderItem
WHERE OrderID = <specified order ID>
GROUP BY OrderID
) AS v1
JOIN (SELECT OrderID AS ID, COUNT(*) AS NB
FROM OrderItem
WHERE OrderID != <specified order ID>
GROUP BY OrderID
) AS v2
ON v1.NA > v2.NB
JOIN (SELECT I1.OrderID AS ID, COUNT(*) AS NC
FROM OrderItem AS I1
JOIN OrderItem AS I2 ON I2.ItemID = I1.ItemID AND I2.OrderID = <specified order ID>
WHERE I1.OrderID != <specified order ID>
GROUP BY I1.OrderID
) AS v3
ON v3.ID = v1.ID
) AS u
WHERE CAST(NC AS NUMERIC) / CAST(NL + NS - NC AS NUMERIC) >= 0.85 -- F
Вы можете заметить, что в этом запросе используется таблица OrderItem; Таблицы заказа и позиции не нужны.
Предупреждение: частично протестированный SQL (caveat lector). Вышеупомянутый SQL, похоже, дает правдоподобные ответы на миниатюрные наборы данных. Я скорректировал требование подобия (0,25, затем 0,55) и получил правдоподобные значения и соответствующую селективность. Однако мои тестовые данные имели только 8 пунктов в самом большом порядке и, разумеется, не охватывали весь объем описанных данных. Поскольку СУБД, который я использую наиболее часто, не поддерживает CTE, SQL ниже не тестируется. Тем не менее, я уверенно уверен, что, если я не допустил большую ошибку, код CTE в версии 1 (с большим количеством повторений указанного идентификатора заказа) должен быть чистым. Я думаю, что версия 2 тоже может быть ОК, но... она не проверена.
Возможно, существуют более компактные способы выражения запроса, возможно, используя функции OLAP.
Если бы я собирался проверить это, я бы создал таблицу с несколькими представительные наборы элементов заказа, проверяя, что мера подобия вернулся был разумным. Я работал бы более или менее, как показано, постепенно создавая сложный запрос. Если одно из выражений показанный как ошибочный, тогда я бы сделал соответствующие корректировки в этом запросе пока дефект не будет исправлен.
Очевидно, что производительность будет проблемой. Самые внутренние запросы не ужасно сложный, но они не тривиальны. Однако измерение покажет, является ли это драматической проблемой или просто неприятностью. изучение могут помочь планы запросов. Кажется весьма вероятным, что индекс на OrderItem.OrderID; запросы вряд ли будут хорошо работать если такого индекса нет. Это вряд ли будет проблемой, поскольку является столбцом внешнего ключа.
Вы можете извлечь выгоду из использования предложений WITH WITH (Общие выражения таблицы). Они будут делать явное повторение, которое подразумевается в двух половинах подзапроса UNION.
Использование общих выражений таблицы
Использование общих табличных выражений разъясняет оптимизатору, когда выражения одинаковы и могут помочь ему работать лучше. Они также помогите людям, читающим ваш запрос. Приведенный выше запрос скорее использование CTE.
Версия 1: Повторение указанного номера заказа
WITH SO AS (SELECT OrderID AS ID, COUNT(*) AS NA -- Specified Order (SO)
FROM OrderItem
WHERE OrderID = <specified order ID>
GROUP BY OrderID
),
OO AS (SELECT OrderID AS ID, COUNT(*) AS NB -- Other orders (OO)
FROM OrderItem
WHERE OrderID != <specified order ID>
GROUP BY OrderID
),
CI AS (SELECT I1.OrderID AS ID, COUNT(*) AS NC -- Common Items (CI)
FROM OrderItem AS I1
JOIN OrderItem AS I2 ON I2.ItemID = I1.ItemID AND I2.OrderID = <specified order ID>
WHERE I1.OrderID != <specified order ID>
GROUP BY I1.OrderID
)
SELECT OrderID_1, NS, OrderID_2, NL, NC,
CAST(NC AS NUMERIC) / CAST(NL + NS - NC AS NUMERIC) AS Similarity
FROM (SELECT v1.ID AS OrderID_1, v1.NA AS NS, v2.ID AS OrderID_2, v2.NB AS NL, v3.NC AS NC
FROM SO AS v1
JOIN OO AS v2 ON v1.NA <= v2.NB
JOIN CI AS v3 ON v3.ID = v2.ID
UNION
SELECT v2.ID AS OrderID_1, v2.NB AS NS, v1.ID AS OrderID_2, v1.NA AS NL, v3.NC AS NC
FROM SO AS v1
JOIN OO AS v2 ON v1.NA > v2.NB
JOIN CI AS v3 ON v3.ID = v1.ID
) AS u
WHERE CAST(NC AS NUMERIC) / CAST(NL + NS - NC AS NUMERIC) >= 0.85 -- F
Версия 2: Избегание повторения указанного номера заказа
WITH SO AS (SELECT OrderID AS ID, COUNT(*) AS NA -- Specified Order (SO)
FROM OrderItem
WHERE OrderID = <specified order ID>
GROUP BY OrderID
),
OO AS (SELECT OI.OrderID AS ID, COUNT(*) AS NB -- Other orders (OO)
FROM OrderItem AS OI
JOIN SO ON OI.OrderID != SO.ID
GROUP BY OI.OrderID
),
CI AS (SELECT I1.OrderID AS ID, COUNT(*) AS NC -- Common Items (CI)
FROM OrderItem AS I1
JOIN SO AS S1 ON I1.OrderID != S1.ID
JOIN OrderItem AS I2 ON I2.ItemID = I1.ItemID
JOIN SO AS S2 ON I2.OrderID = S2.ID
GROUP BY I1.OrderID
)
SELECT OrderID_1, NS, OrderID_2, NL, NC,
CAST(NC AS NUMERIC) / CAST(NL + NS - NC AS NUMERIC) AS Similarity
FROM (SELECT v1.ID AS OrderID_1, v1.NA AS NS, v2.ID AS OrderID_2, v2.NB AS NL, v3.NC AS NC
FROM SO AS v1
JOIN OO AS v2 ON v1.NA <= v2.NB
JOIN CI AS v3 ON v3.ID = v2.ID
UNION
SELECT v2.ID AS OrderID_1, v2.NB AS NS, v1.ID AS OrderID_2, v1.NA AS NL, v3.NC AS NC
FROM SO AS v1
JOIN OO AS v2 ON v1.NA > v2.NB
JOIN CI AS v3 ON v3.ID = v1.ID
) AS u
WHERE CAST(NC AS NUMERIC) / CAST(NL + NS - NC AS NUMERIC) >= 0.85 -- F
Ни одно из них не читается легко; оба они легче, чем большой SELECT с выписанными CTE.
Минимальные тестовые данные
Это неадекватно для хорошего тестирования. Это дает небольшую доволенную уверенность (и это обнаружило проблему с запросом "идентичный заказ".
CREATE TABLE Order (ID SERIAL NOT NULL PRIMARY KEY);
CREATE TABLE Item (ID SERIAL NOT NULL PRIMARY KEY);
CREATE TABLE OrderItem
(
OrderID INTEGER NOT NULL REFERENCES Order,
ItemID INTEGER NOT NULL REFERENCES Item,
Quantity DECIMAL(8,2) NOT NULL
);
INSERT INTO Order VALUES(1);
INSERT INTO Order VALUES(2);
INSERT INTO Order VALUES(3);
INSERT INTO Order VALUES(4);
INSERT INTO Order VALUES(5);
INSERT INTO Order VALUES(6);
INSERT INTO Order VALUES(7);
INSERT INTO Item VALUES(111);
INSERT INTO Item VALUES(222);
INSERT INTO Item VALUES(333);
INSERT INTO Item VALUES(444);
INSERT INTO Item VALUES(555);
INSERT INTO Item VALUES(666);
INSERT INTO Item VALUES(777);
INSERT INTO Item VALUES(888);
INSERT INTO Item VALUES(999);
INSERT INTO OrderItem VALUES(1, 111, 1);
INSERT INTO OrderItem VALUES(1, 222, 1);
INSERT INTO OrderItem VALUES(1, 333, 1);
INSERT INTO OrderItem VALUES(1, 555, 1);
INSERT INTO OrderItem VALUES(2, 111, 1);
INSERT INTO OrderItem VALUES(2, 222, 1);
INSERT INTO OrderItem VALUES(2, 333, 1);
INSERT INTO OrderItem VALUES(2, 555, 1);
INSERT INTO OrderItem VALUES(3, 111, 1);
INSERT INTO OrderItem VALUES(3, 222, 1);
INSERT INTO OrderItem VALUES(3, 333, 1);
INSERT INTO OrderItem VALUES(3, 444, 1);
INSERT INTO OrderItem VALUES(3, 555, 1);
INSERT INTO OrderItem VALUES(3, 666, 1);
INSERT INTO OrderItem VALUES(4, 111, 1);
INSERT INTO OrderItem VALUES(4, 222, 1);
INSERT INTO OrderItem VALUES(4, 333, 1);
INSERT INTO OrderItem VALUES(4, 444, 1);
INSERT INTO OrderItem VALUES(4, 555, 1);
INSERT INTO OrderItem VALUES(4, 777, 1);
INSERT INTO OrderItem VALUES(5, 111, 1);
INSERT INTO OrderItem VALUES(5, 222, 1);
INSERT INTO OrderItem VALUES(5, 333, 1);
INSERT INTO OrderItem VALUES(5, 444, 1);
INSERT INTO OrderItem VALUES(5, 555, 1);
INSERT INTO OrderItem VALUES(5, 777, 1);
INSERT INTO OrderItem VALUES(5, 999, 1);
INSERT INTO OrderItem VALUES(6, 111, 1);
INSERT INTO OrderItem VALUES(6, 222, 1);
INSERT INTO OrderItem VALUES(6, 333, 1);
INSERT INTO OrderItem VALUES(6, 444, 1);
INSERT INTO OrderItem VALUES(6, 555, 1);
INSERT INTO OrderItem VALUES(6, 777, 1);
INSERT INTO OrderItem VALUES(6, 888, 1);
INSERT INTO OrderItem VALUES(6, 999, 1);
INSERT INTO OrderItem VALUES(7, 111, 1);
INSERT INTO OrderItem VALUES(7, 222, 1);
INSERT INTO OrderItem VALUES(7, 333, 1);
INSERT INTO OrderItem VALUES(7, 444, 1);
INSERT INTO OrderItem VALUES(7, 555, 1);
INSERT INTO OrderItem VALUES(7, 777, 1);
INSERT INTO OrderItem VALUES(7, 888, 1);
INSERT INTO OrderItem VALUES(7, 999, 1);
INSERT INTO OrderItem VALUES(7, 666, 1);