У меня есть тройственные отношения, в которых я устанавливаю связь между предложениями, профилями и навыками. Например, таблица тройственных отношений, называемая ternary
, имеет идентификаторы трех таблиц в качестве первичного ключа. Это может выглядеть примерно так:
id_Offer - id_Profile - id_Skill
1 - 1 - 1
1 - 1 - 2
1 - 1 - 3
1 - 2 - 1
2 - 1 - 1
2 - 3 - 2
2 - 1 - 3
2 - 5 - 1
[and so on, there would be more registers for each id_Offer from Offer but I want to limit the example]
Таким образом, у меня есть 2 предложения в целом, с несколькими профилями в каждом из них.
Таблица Предложение выглядит примерно так:
Offer - business_name
1 - business-1
2 - business-1
3 - business-1
4 - business-1
5 - business-2
6 - business-2
7 - business-2
8 - business-3
Поэтому, когда я делаю запрос типа
select distinct id_offer, business_name, COUNT(*)
FROM Offer
GROUP BY business_name
Order by COUNT(*);
Я получаю это для бизнеса-1 У меня есть 4 предложения.
Теперь, если я хочу принять во внимание предложения для некоторого профиля, я должен присоединиться к моим тройственным отношениям. Но даже если я сделаю так просто, как следующее
select distinct business_name
from Offer
INNER JOIN ternary ON Offer.id_Offer = ternary.id_Offer
GROUP BY business_name
WHERE business_name = 'business-1'
Независимо от того, что я положил на группу, или, если я пишу отдельно или нет, я не получаю то, что хочу. Реальность такова, что для business-1 у меня есть 4 предложения. Прямо сейчас в тройном появятся только два. Поэтому он должен вернуть 2 уникальных предложения для этого имени без фильтрации по профилю.
Но вместо этого я получаю 8 предложений, потому что это то, сколько раз он появляется в тройном, id_Offer, который соответствует.
Как это сделать? Если мне не нужны фильтры, я могу просто взглянуть на таблицу предложений. Но что, если мне нужно отфильтровать id_skill или id_Profile И хотите вернуть бизнес-имя?
Я видел такие решения, как это, но я не могу заставить их работать, я не понимаю, что ?
как это называется, чтобы узнать больше об этом, если MariaDB работает одинаково в этом смысле, я не мог найти информацию об этом, потому что я не знаю, как называется эта операция. Когда я пытаюсь построить этот запрос для своих данных, я получаю:
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '? ORDER BY COUNT(*) DESC' at line 1
Но, как я уже сказал, трудно найти "?". как... Оператор? Функция?
Существует два основных решения.
SELECT
o.business_name,
COUNT(DISTINCT o.id_offer) AS unique_offers
FROM
Offer AS o
INNER JOIN
ternary AS t
ON t.id_Offer = o.id_Offer
WHERE
o.business_name = 'business-1'
AND t.id_profile IN (1, 2, 3, 5)
GROUP BY
o.business_name
Это самый простой способ написать и подумать. Но это также может быть довольно интенсивным, потому что вы все еще присоединяетесь к каждой строке, offer
4 строки в ternary
Создание 8 строк для агрегирования и обработки через DISTINCT
.
"Лучше" (на мой взгляд) маршрут состоит в том, чтобы затем фильтровать совокупность ternary
таблицы в подзапросе.
SELECT
o.business_name,
COUNT(*) AS unique_offers
FROM
Offer AS o
INNER JOIN
(
SELECT id_Offer
FROM ternary
WHERE id_profile IN (1, 2, 3, 5)
GROUP BY id_Offer
)
AS t
ON t.id_Offer = o.id_Offer
WHERE
o.business_name = 'business-1'
GROUP BY
o.business_name
Это гарантирует, что t
только когда-либо имеет один ряд для любого данного предложения. Это, в свою очередь, означает, что каждая строка, offer
только когда-либо, присоединяется к одной строке в t
; нет дублирования. Это, в свою очередь, означает, что нет необходимости использовать COUNT(DISTINCT)
и снимает некоторые накладные расходы (переместив его во внутренний запрос GROUP BY
).
id_offer == 1
включен в профили 1 и 2. А id_offer == 2
включен в профили 1 и 3 и 5. Так что нет, они не должны складываться ... Offers_For_Profile_1
(2) + Offers_For_Profile_2
(1) будет выше, чем Offers_For_Profile_1_Or_2
(2) ...
Вы говорите, что хотите видеть предложения для определенного бизнеса, но вы хотите ограничить их в соответствии с определенными профилями или навыками?
Мы ограничиваем результаты запроса в WHERE
. Если мы хотим искать данные в другой таблице, мы используем IN
или EXISTS
. Например:
select *
from offer
where business_name = 'business-1'
and id_offer in
(
select id_offer
from ternary
where id_profile = 1
and id_skill = 2
);