Как сделать внутреннее соединение, сохраняя уникальные строки - PullRequest
0 голосов
/ 24 мая 2018

У меня есть троичные отношения, в которых я фиксирую отношения между предложениями, профилями и навыками.Таблица троичных отношений, называемая, например, 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(*);

, я получаю это для business-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'

Независимо от того, что я добавляю в группу, или если я пишу по-другому или нет, я не получаю то, что хочу.Реальность такова, что для бизнеса-1 у меня есть 4 предложения.Прямо сейчас в троице только два.Таким образом, он должен вернуть 2 уникальных предложения для этого имени без фильтрации по профилю.

Но вместо этого я получаю 8 предложений, потому что именно столько раз оно появляется в троичной системе, то есть совпадают id_Offer.

Как это сделать?Если мне не нужны фильтры, я могу просто посмотреть на таблицу предложений в одиночку.Но что, если мне нужно отфильтровать по id_skill или id_Profile И хотите вернуть business_name?

Я видел такие решения, как this , но я не могу заставить их работать, я не понимаю, что?, как это называется, чтобы узнать больше об этом, если 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

Но, как я уже сказал, это довольно сложно найти '?'как ... оператор?Функция

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Вы говорите, что хотите видеть предложения для определенного бизнеса, но хотите ограничить их в соответствии с определенными профилями или навыками?

Мы ограничиваем результаты запроса в предложении 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
);
0 голосов
/ 24 мая 2018

Существует два основных решения.

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) .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...