Предположим, что у меня есть следующая таблица отношения родитель/ребенок в моей базе данных:Родитель/Детские столы Query Pattern
TABLE offer_master(offer_id int primary key, ..., scope varchar) TABLE offer_detail(offer_detail_id int primary key, offer_id int foreign key, customer_id int, ...)
где offer_master.scope
может принимать значение
- ИНДИВИДУАЛЬНЫЙ: когда предложение предназначено для конкретных клиентов. В этом случае всякий раз, когда строка вставлена в
offer_master
, соответствующая строка равна , добавленной кoffer_detail
для каждого клиента, которому было предложено предложение.
например.
INSERT INTO offer_master(1, ..., 'INDIVIDUAL'); INSERT INTO offer_detail(offer_detail_id, offer_id, customer_id, ...) VALUES (1, 1, 100, ...) INSERT INTO offer_detail(offer_detail_id, offer_id, customer_id, ...) VALUES (2, 1, 101, ...)
- GLOBAL: когда предложение сделано для всех клиентов. В этом случае, новые предложения могут быть добавлены в родительской таблице следующим образом:
INSERT INTO offer_master(2, ..., 'GLOBAL'); INSERT INTO offer_master(3, ..., 'GLOBAL');
но ребенок добавляется строка offer_detail
только , когда клиент указывает определенный интерес к предложению. Так это может быть так, что в каком-то позже мы будем иметь
INSERT INTO offer_detail(offer_detail_id, offer_id, customer_id, ...) VALUES (4, 3, 100, ...)
Учитывая эту ситуацию, предположим, что мы хотели бы запросить базу данных , чтобы получить все предложения, которые были распространены на клиент 100
; это включает в себя 3 вида предложений:
- предложения, которые были расширены специально для клиента
100
. - глобальные предложения, которые клиент
100
не проявляли никакого интереса к - глобальные предложения, которые клиент
100
сделал показать заинтересованность в
я вижу два подхода:..
- Использование подзапроса:
SELECT * FROM offer_master WHERE offer_id in ( SELECT offer_id FROM offer_detail WHERE customer_id = 100) OR scope = 'GLOBAL'
- Использование UNION
SELECT om.* FROM offer_master om INNER JOIN offer_detail od ON om.offer_id = od.offer_id WHERE od.customer_id = 100 UNION SELECT * FROM offer_master WHERE scope = 'GLOBAL'
Примечание: aUNION ALL
не может использоваться, поскольку глобальное предложение , которое клиент проявил интерес к нему, будет дублироваться.
Мой вопрос:
- есть ли этот шаблон запроса имя?
- Какой из двух методов запроса предпочтительнее?
- Должен ли быть усовершенствован проект базы данных?
Использование одной таблицы для обозначения двух разных вещей - плохая идея. Ваш Offer_detail означает, что «предложение сделано конкретным клиентам» * и * «клиент указывает на некоторый интерес к предложению». Исправьте это первым. –
Я думаю, что таблица Offer_detail в настоящее время представляет предложения, сделанные конкретным клиентам * или *, которые клиент указал на некоторый интерес к предложению. –
Каждая строка в таблице должна иметь один и тот же предикат - такой же смысл. Это означает * один смысл, а не два. Если одна строка представляет сделанные предложения, а другая строка представляет интерес для клиентов, у вас есть проблема с дизайном. Исправьте это первым. –