Как отфильтровать набор результатов SQL на основе столбца с псевдонимами, в котором используется МАТЕРИАЛ ДЛЯ ПУТИ XML

#sql

Вопрос:

У меня есть столбец, который использует псевдоним в моем SQL-запросе. Результаты столбца с псевдонимами представляют собой разделенные запятыми списки языков, на которых говорит учитель.

 SELECT 
    Teacher.LastName, 
    STUFF((SELECT DISTINCT ', '   COALESCE((TeacherLanguage.LanguageName), '')
           FROM TeacherLanguage 
           INNER JOIN TeacherLanguageRel ON Teacher.TeacherId = TeacherLanguage.TeacherId
                  AND TeacherLanguage.LanguageId = TeacherLanguageRel.LanguageId 
           FOR XML PATH('')), 1, 1, '') AS 'Languages' 
FROM 
    Teacher
 

Есть ли способ отфильтровать результаты, используя значения в столбце Языки? Прикрепление оператора WHERE к концу запроса, похоже, не работает.

Например

 WHERE Languages LIKE '%spanish%'
 

приводит к ошибке:

Недопустимое имя столбца «Языки».

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

1. Вы не можете ссылаться на столбец по его псевдониму в WHERE . Хотя я бы рекомендовал EXISTS в WHERE .

2. Какие СУБД вы используете? Я бы ожидал, что ошибка уже AS 'Languages' произошла .

3. Кроме того, помечайте только те СУБД, которые вы действительно используете. MySQL и SQL Server-это совершенно разные продукты.

4. Вы можете обернуть свой оператор как есть во внешний выбор, хотя фильтрация с помощью a where exists() была бы более эффективной.

5. ТАМ, где СУЩЕСТВУЕТ, оказалось именно то, что мне было нужно, спасибо!

Ответ №1:

Вы не можете сделать то, что намереваетесь, с существующим запросом, так как where предложение оценивается до определения Languages псевдонима.

Вы могли бы сделать то, что вы намереваетесь, превратив существующий запрос в производную таблицу, заключив во внешнюю выборку,

 select * from (
  <your existing query>
)t
where Languages like '%spanish%'
 

Однако это будет означать, что вы читаете строки, которые вам не нужны, которые вы могли бы просто отфильтровать в своем текущем запросе. Я считаю, что должно сработать следующее — конечно, непроверенное.

 select t.LastName, Stuff((
        select distinct ', '   Coalesce((TeacherLanguage.LanguageName), '')
        from TeacherLanguage tl
        join TeacherLanguageRel tlr on tlr.LanguageId=tl.LanguageId
        where tl.TeacherId=t.TeacherId
            and tl.language like '%spanish%'
        for xml path('')
    ), 1, 1, '') as Languages
from Teacher t
 

Обратите внимание, что я использовал псевдонимы столбцов в вашем запросе, и кавычки должны быть зарезервированы для строковых литералов, а не для псевдонимов столбцов — Languages это не зарезервированное слово, так что все в порядке. Это также, конечно, предполагает SQL Server.

Кроме того, начиная с SQL Server 2017, for XML path он устарел и может быть заменен на string_agg .