Использование LIKE со списком значений из подзапроса - PullRequest
0 голосов
/ 05 июля 2019

У меня есть таблица сообщений с комментариями, в которых иногда ОП «выкрикивает» другой постер (поэтому текст выглядит как '%@Id%', где Id - это идентификатор другого постера в этой теме). Я пытаюсь придумать какой-то запрос, чтобы я мог вернуть исходное сообщение и выкрикнуть комментарии. Я думал, что смогу сделать это с помощью рекурсивного запроса, но я получаю код ошибки.

SELECT p.CreatedBy AS OP, p.Post AS FirstPost, c.Comment AS ShoutOut
    FROM Posts p INNER JOIN Comments c ON p.Id=c.PostId
    WHERE p.CreatedBy=c.CreatedBy AND c.Comment LIKE '%' + 
        (SELECT cc.CreatedBy
            FROM Comments cc
            WHERE cc.PostId=p.Id) + '%'

Это возвращается

Сообщение 512, уровень 16, состояние 1, строка 190 "Подзапрос возвратил более 1 значение. Это недопустимо, если подзапрос следует <,>,> =, <=, =,! = или когда подзапрос используется в качестве выражения. "</p>

Есть идеи о том, что я должен делать вместо этого?

Ответы [ 2 ]

0 голосов
/ 06 июля 2019

LIKE является оператором двух скалярных значений, поэтому он ожидает, что правая сторона будет одним значением. Но запрос возвращает много - так что вы получите ошибку.

Вместо одного LIKE вам нужно условие EXISTS (хотя у меня нет SqlServer для проверки синтаксиса), которое проверяет, есть ли в cc другие комментарии, удовлетворяющие условию LIKE:

...  
AND EXISTS (SELECT 1 FROM Comments cc 
            WHERE cc.PostId = p.Id AND 
                c.Comment LIKE '%' + cc.CreatedBy + '%')

Еще один способ выразить это - 3-way JOIN:

SELECT p.CreatedBy AS OP, p.Post AS FirstPost, c.Comment AS ShoutOut
FROM Posts p 
INNER JOIN Comments c ON p.Id = c.PostId
INNER JOIN Comments cc ON p.Id = cc.PostId
WHERE p.CreatedBy = c.CreatedBy AND 
      c.Comment LIKE '%' + cc.CreatedBy + '%'
GROUP BY OP, FirstPost, ShootOut

В этой версии требуется GROUP BY, чтобы исключить дублирование, поскольку один ShootOut может быть объединен с несколькими комментариями из cc одним и тем же автором. Так что это может быть менее эффективно (но для уверенности нужно взглянуть на план запроса).

0 голосов
/ 06 июля 2019

Я думаю, это приблизит вас:

SELECT p.CreatedBy AS OP, 
p.Post AS FirstPost, 
c.Comment AS ShoutOut
FROM Posts p 
INNER JOIN Comments c 
  ON p.Id=c.PostId
INNER JOIN Comments so
  ON CHARINDEX(c.Comment,'%@' + cast(so.Id as varchar(8)) + '%') > 0
WHERE p.CreatedBy=c.CreatedBy
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...