SQL-запрос с использованием STRING_AGG, дающий дубликаты при соединении 3 таблицы

#sql #sql-server

Вопрос:

Я пытаюсь объединить 3 таблицы вместе (Событие, Символ, Категория). Это основной дизайн

Таблица Событий:

 Id | Title
-----------
 1 | Testing
 3 | Debugging
 

Таблица Символов:

 Event_Id | Symbol
-----------------
    1    |  TT
    1    |  UU
 

Таблица Категорий:

 Event_Id |  Category
--------------------
    1    |   XV
    1    |   XX
    3    |   XL
 

Запрос на объединение, который я написал, таков:

 SELECT event.Id , STRING_AGG(symbol.symbol, ',') symbol, STRING_AGG(category.category, ',') as category 
FROM Event as event 
    LEFT JOIN Category category ON event.publisherID = category.Id
    LEFT JOIN Symbol symbol on event.publisherID = symbol.Id
GROUP BY event.Id
 

Результаты, которые я получаю, таковы:

 Id |     symbol    |  category
---------------------------------
 1 |  TT,UU,TT,UU  | XV,XV,XX,XX
 3 |     NULL      |    XL
 

Как мне сделать так, чтобы в столбцах символов и категорий не было дубликатов?

Ответ №1:

Это тот случай, в котором OUTER APPLY есть большая помощь:

 SELECT e.Id , s.symbols, c.categories 
FROM Event e OUTER APPLY
     (SELECT STRING_AGG(c.category, ',') as categories
      FROM Category c
      WHERE e.publisherID = c.Id
     ) c OUTER APPLY
     (SELECT STRING_AGG(s.symbol, ',') as symbols
      FROM Symbol s
      WHERE e.publisherID = s.Id
     ) s;
 

Избегая внешней агрегации, это также должно быть быстрее. Я должен отметить, что вышесказанное очень похоже на коррелированные подзапросы:

 SELECT e.Id , s.symbols, c.categories 
       (SELECT STRING_AGG(c.category, ',')
        FROM Category c
        WHERE e.publisherID = c.Id
       ) as categories,
       (SELECT STRING_AGG(s.symbol, ',')
        FROM Symbol s
        WHERE e.publisherID = s.Id
       ) as symbols
FROM Event e;
 

Комментарии:

1. Слишком быстро! Вы знаете, они помешали Фарли, прибавив 135 фунтов. Возможно, мы могли бы убедить вас надеть прихватки для духовки.