Как сделать несколько агрегированных столбцов в операторе выбора - PullRequest
0 голосов
/ 22 января 2010

Просто, чтобы избежать быстрых ответов, я упомяну, что я не использую MySQL, поэтому я не могу использовать GROUP_CONCAT, и что я также рассмотрел этот вопрос уже.

Пример
(это не те данные, с которыми я работаю, но они точно описывают мой случай)
Персональная таблица, с идентификатором, столбцы Имя
Таблица Person_CountriesVisited с столбцами PersonID, Country (таблица связей 1..M)
Таблица Person_StatesVisited с PersonID, столбцы State (таблица ссылок 1..M)

Ограничения
Я не могу изменить БД. Я также не могу изменить большую часть кода, так что это должно быть сделано в SQL, а не в коде после выполнения запроса.

Желаемый результат
Результирующий набор со столбцами

Person.ID,
Person.Name,
[список связанных Person_CountriesVisited.Country],
[список связанных Person_StatesVisited.State],

который также может быть отфильтрован общим поисковым термином, который применяется ко всем столбцам.

Мои попытки

Теперь, мой SQL-фу не такой уж и острый в наши дни, но я делаю все, что могу, основываясь на примерах, которые я нашел.

1) Я пытался использовать скалярный подзапрос:

ВЫБРАТЬ P.ID, P.Name,
(выберите CV.Country + ','
ОТ Person_CountriesVisited CV ON P.ID = CV.PersonId
ДЛЯ ПУТИ XML ('')) AS Страны, которые посетили,
(ВЫБРАТЬ SV.State + ','
FROM Person_StatesVisited SV ON P.ID = SV.PersonId
FOR XML PATH ('')) ASSVisited

ОТ ЛИЧНОСТИ P

ГДЕ P.Name LIKE '%' + @SearchTerm + '%'
ИЛИ СтраныПосещенные как "%" + @SearchTerm + '%'
ИЛИ StatesVisted LIKE '%' + @SearchTerm + '%'

Который возвращает данные, которые я хочу, но только когда я удаляю предложение WHERE. Он не работает с предложением WHERE, потому что SQL Server 2005, похоже, не нравится, что я ссылаюсь на столбец, созданный из скалярного подзапроса в предложении WHERE. Это выдает мне сообщение об ошибке «Неверное имя столбца« Страны, в которых вы находитесь »» (и снова для столбца «Посещенные Штаты»).

2) Я попробовал трюк с применением кросса:

ВЫБРАТЬ P.ID, P.Name, Страны, которые посетили, Посещенные Штаты

ОТ ЛИЦА П
INNER JOIN Person_CountriesVisited CV ON P.ID = CV.PersonID
ПРИМЕНИТЬ КРЕСТ (
ВЫБЕРИТЕ CV.Country + ','
ОТ ЧЕЛОВЕКА P2 ВНУТРЕННЯЯ РЕШЕНИЕ Person_CountriesVisited CV ON P2.ID = CV.PersonID
ГДЕ P.ID = P2.ID
ДЛЯ ПУТИ XML ('')
) PRE_TRIMMED (посещенные страны)

INNER JOIN Person_StatesVisited SV ON P.ID = SV.PersonID
CROSS APPLY (
ВЫБРАТЬ SV.State + ','
ОТ ЛИЦА P2 ВНУТРЕННЕЕ ПРИСОЕДИНЕНИЕ Person_StatesVisited SV ON P2.ID = SV.PersonID FOR XML PATH ('')
) PRE_TRIMMED (StatesVisited)

ГДЕ P.Name LIKE '%' + @SearchTerm + "%"
ИЛИ Страны, которые посещали, КАК "%" + @SearchTerm + '%'
ИЛИ StatesVisted LIKE '%' + @SearchTerm + '%'

Но это тоже не работает, так как вы, очевидно, не можете иметь несколько вызовов pre_trimmed.

У кого-нибудь есть предложения для меня?

1 Ответ

3 голосов
/ 22 января 2010

Вам просто нужно присвоить псевдониму свои подзапросы:

WITH x AS (
  SELECT P.ID
        ,P.Name
        ,( select CV.Country + ', '
         FROM Person_CountriesVisited CV ON P.ID = CV.PersonId 
         FOR XML PATH ('')
        ) AS CountriesVisited
        ,( SELECT SV.State + ', '
         FROM Person_StatesVisited SV ON P.ID = SV.PersonId 
         FOR XML PATH ('')
        ) AS StatesVisited
  FROM Person P
)
SELECT *
FROM X    
WHERE Name LIKE '%' + @SearchTerm + '%'
  OR CountriesVisited LIKE '%' + @SearchTerm + '%'
  OR StatesVisted LIKE '%' + @SearchTerm + '%'

Вы можете сделать нечто подобное во втором примере. На самом деле во втором примере, просто псевдоним второго подзапроса, как что-то новое, как PRE_TRIMMED2.

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