Объединить поиск из 1 таблицы в несколько столбцов - PullRequest
1 голос
/ 21 марта 2019

Как связать 1 таблицу с несколькими столбцами в другой таблице без использования многократного запроса JOIN?Вот мой сценарий:

У меня есть таблица User с ID и Name

User
+---------+------------+
|      Id |       Name |
+---------+------------+
|       1 |       John |
|       2 |       Mike |
|       3 |    Charles |
+---------+------------+

И таблица Product с несколькими столбцами, но только фокус на 2 столбцах CreateBy И ModifiedBy

+------------+-----------+-------------+
| product_id | CreateBy  | ModifiedBy  |
+------------+-----------+-------------+
|       1    | 1         | 3           |
|       2    | 1         | 3           |
|       3    | 2         | 3           |
|       4    | 2         | 1           |
|       5    | 2         | 3           |
+------------+-----------+-------------+

При нормальном JOIN мне нужно сделать 2 РЕЙСА:

SELECT p.Product_id,
    u1.Name AS CreateByName,
    u2.Name AS ModifiedByName
FROM Product p
JOIN USER user u1 ON p.CreateBy = u1.Id,
JOIN USER user u2 ON p.ModifiedBy = u2.Id

, чтобы получить результат

+------------+---------------+-----------------+
| product_id | CreateByName  | ModifiedByName  |
+------------+---------------+-----------------+
|       1    | John          | Charles         |
|       2    | John          | Charles         |
|       3    | Mike          | Charles         |
|       4    | Mike          | John            |
|       5    | Mike          | Charles         |
+------------+---------------+-----------------+

Как мне избежать этого 2 раза JOIN?

Я использую MS-SQL, но открыт для всех запросов SQL для моего собственного любопытного изучения

Ответы [ 3 ]

1 голос
/ 21 марта 2019

Если вы используете естественные ключи вместо суррогатов, вам вообще не нужно присоединяться. Я не знаю, как вы отличаете свои продукты в реальном мире, но для примера я предполагаю, что у вас есть UPC

CREATE TABLE User 
(Name VARCHAR(20) PRIMARY KEY);
CREATE TABLE Product 
(UPC CHAR(12) PRIMARY KEY, 
CreatedBy VARCHAR(20) REFERENCES User(Name),
ModifiedBy VARCHAR(20) REFERENCES User(Name)
);

Теперь ваш запрос является простым выбором, и вы также применяете уникальность ваших имен пользователей в качестве бонуса, и вам не нужны дополнительные индексы. Попробуй это ...

НТН

1 голос
/ 21 марта 2019

Присоединение - лучший подход, но если вы ищете альтернативный подход, вы можете использовать Inline Query.

SELECT P.PRODUCT_ID,
       (SELECT [NAME] FROM @USER WHERE ID = CREATED_BY) AS CREATED_BY,
       (SELECT [NAME] FROM @USER WHERE ID = MODIFIED_BY) AS MODIFIED_BY
FROM @PRODUCT P

DEMO

1 голос
/ 21 марта 2019

Ваш текущий дизайн / подход приемлем, я думаю, и необходимость двух объединений является функцией наличия двух столбцов идентификатора пользователя.Каждый из двух столбцов требует отдельного объединения.

Для забавы, вот таблица, которую вы можете рассмотреть, если действительно хотите выполнить только одно соединение:

+------------+-----------+-------------+
| product_id | user_id   | type        |
+------------+-----------+-------------+
|       1    | 1         | created     |
|       2    | 1         | created     |
|       3    | 2         | created     |
|       4    | 2         | created     |
|       5    | 2         | created     |
|       1    | 3         | modified    |
|       2    | 3         | modified    |
|       3    | 3         | modified    |
|       4    | 1         | modified    |
|       5    | 3         | modified    |
+------------+-----------+-------------+

Сейчасвы можете обойтись одним простым соединением с последующей агрегацией:

SELECT
    p.product_id,
    MAX(CASE WHEN t.type = 'created'  THEN u.Name END) AS CreateByName,
    MAX(CASE WHEN t.type = 'modified' THEN u.Name END) AS ModifiedByName
FROM Product p
INNER JOIN user u
    ON p.user_id = u.Id
GROUP BY
    p.product_id;

Обратите внимание, что я не рекомендую этот подход вообще.Гораздо чище использовать ваш текущий подход и использовать два соединения.Объединения могут быть довольно легко оптимизированы с использованием одного или нескольких индексов.Приведенный выше метод агрегирования, вероятно, не будет работать так же хорошо, как у вас.

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