SQL-запрос, который выдает различные результаты, соответствующие нескольким столбцам
Вопрос
Извините, я не смог придумать лучшего названия для своей проблемы, поскольку я совсем новичок в SQL.Я ищу строку SQL-запроса, которая решает приведенную ниже проблему.
Давайте предположим, что следующая таблица:
DOCUMENT_ID | TAG ---------------------------- 1 | tag1 1 | tag2 1 | tag3 2 | tag2 3 | tag1 3 | tag2 4 | tag1 5 | tag3
Теперь я хочу выбрать все отдельные идентификаторы документа, которые содержат один или несколько тегов (но они должны содержать все указанные теги).Например:Выберите все document_id с tag1, и tag2 вернет 1 и 3 (но не 4, например, поскольку у него нет tag2).
Каков был бы наилучший способ сделать это?
С уважением, Кай
Решение
SELECT document_id
FROM table
WHERE tag = 'tag1' OR tag = 'tag2'
GROUP BY document_id
HAVING COUNT(DISTINCT tag) = 2
Редактировать:
Обновлено из-за отсутствия ограничений...
Другие советы
Это предполагает, что documentId и Tag являются первичным ключом.
Редактировать:Изменено предложение HAVING для подсчета РАЗЛИЧНЫХ тегов.Таким образом, не имеет значения, что такое первичный ключ.
Тестовые данные
-- Populate Test Data
CREATE TABLE #table (
DocumentID varchar(8) NOT NULL,
Tag varchar(8) NOT NULL
)
INSERT INTO #table VALUES ('1','tag1')
INSERT INTO #table VALUES ('1','tag2')
INSERT INTO #table VALUES ('1','tag3')
INSERT INTO #table VALUES ('2','tag2')
INSERT INTO #table VALUES ('3','tag1')
INSERT INTO #table VALUES ('3','tag2')
INSERT INTO #table VALUES ('4','tag1')
INSERT INTO #table VALUES ('5','tag3')
INSERT INTO #table VALUES ('3','tag2') -- Edit: test duplicate tags
Запрос
-- Return Results
SELECT DocumentID FROM #table
WHERE Tag IN ('tag1','tag2')
GROUP BY DocumentID
HAVING COUNT(DISTINCT Tag) = 2
Результаты
DocumentID
----------
1
3
select DOCUMENT_ID
TAG in ("tag1", "tag2", ... "tagN")
group by DOCUMENT_ID
having count(*) > N and
Измените N и список тегов по мере необходимости.
Select distinct document_id
from {TABLE}
where tag in ('tag1','tag2')
group by id
having count(tag) >=2
То, как вы генерируете список тегов в предложении where, зависит от структуры вашего приложения.Если вы динамически генерируете запрос как часть своего кода, то вы могли бы просто сконструировать запрос как большую динамически генерируемую строку.
Мы всегда использовали хранимые процедуры для запроса данных.В этом случае мы передаем список тегов в виде XML-документа.- подобная процедура могла бы выглядеть примерно как одна из этих, где входным аргументом было бы
<tags>
<tag>tag1</tag>
<tag>tag2</tag>
</tags>
CREATE PROCEDURE [dbo].[GetDocumentIdsByTag]
@tagList xml
AS
BEGIN
declare @tagCount int
select @tagCount = count(distinct *) from @tagList.nodes('tags/tag') R(tags)
SELECT DISTINCT documentid
FROM {TABLE}
JOIN @tagList.nodes('tags/tag') R(tags) ON {TABLE}.tag = tags.value('.','varchar(20)')
group by id
having count(distict tag) >= @tagCount
END
или
CREATE PROCEDURE [dbo].[GetDocumentIdsByTag]
@tagList xml
AS
BEGIN
declare @tagCount int
select @tagCount = count(*) from @tagList.nodes('tags/tag') R(tags)
SELECT DISTINCT documentid
FROM {TABLE}
WHERE tag in
(
SELECT tags.value('.','varchar(20)')
FROM @tagList.nodes('tags/tag') R(tags)
}
group by id
having count( distinct tag) >= @tagCount
END
КОНЕЦ