TSQL-запрос для поиска строк, соответствующих набору свойств - PullRequest
5 голосов
/ 22 апреля 2011

У меня есть следующая упрощенная схема:

CREATE TABLE [file]
( 
    id UNIQUEIDENTIFIER NOT NULL, 
    uri NVARCHAR(MAX) NOT NULL, 
    CONSTRAINT PK_file PRIMARY KEY (id ASC) ON [PRIMARY] 
)

CREATE TABLE [property]
( 
    id UNIQUEIDENTIFIER NOT NULL, 
    name NVARCHAR(MAX) NOT NULL, 
    CONSTRAINT PK_property PRIMARY KEY (id ASC) ON [PRIMARY] 
)

CREATE TABLE [metadata]
( 
    fileid UNIQUEIDENTIFIER NOT NULL,
    propertyid UNIQUEIDENTIFIER NOT NULL,
    value NVARCHAR(MAX) NOT NULL, 
    CONSTRAINT PK_metadata PRIMARY KEY (fileid, propertyid ASC) ON [PRIMARY] 
)

Где [fileid] ФК до [file].[id] и [propertyid] ФК до [property].[id]. Предположим, что [properyid] это CLUSTERED и [value] это NON-CLUSTERED.

Я хочу выбрать все файлы, которые соответствуют определенному набору метаданных; например, каждый файл, который имеет пару значений свойства size = 1 Kb и extension = 'txt'.

Запрос, который я создал, например, с указанием трех свойств, выглядит следующим образом:

SELECT [uri] FROM [file] WHERE [id] IN (
    SELECT a.[fileid] FROM (
        SELECT COUNT(*) [count], [fileid] FROM [metadata]
        WHERE ([propertyid] = '597ddddf-afd2-414f-9774-36f067038064' AND 
                [value] = N'moo') OR
              ([propertyid] = 'd83d12de-e4bc-4d18-be12-743504df3318' AND 
                [value] = N'foo') OR
              ([propertyid] = 'c00c3966-5034-4818-8567-abd660f37f15' AND 
                [value] = N'boo')
        GROUP BY [fileid]
    ) a
    WHERE a.[count] = 3
)

Могу ли я быть лучше?

Ответы [ 3 ]

6 голосов
/ 22 апреля 2011
;WITH propertylist AS (
  SELECT propertyid = '597ddddf-afd2-414f-9774-36f067038064', value = N'moo' UNION ALL
  SELECT propertyid = 'd83d12de-e4bc-4d18-be12-743504df3318', value = N'foo' UNION ALL
  SELECT propertyid = 'c00c3966-5034-4818-8567-abd660f37f15', value = N'boo'
)
SELECT uri
FROM file
WHERE id IN (
  SELECT m.fileid
  FROM metadata m
    INNER JOIN propertylist p ON m.propertyid = p.propertyid AND m.value = p.value
  GROUP BY m.fileid
  HAVING COUNT(*) = (SELECT COUNT(*) FROM propertylist)
)
2 голосов
/ 22 апреля 2011

Может как то так?

SELECT 
   [uri] 
FROM 
   [file] 
WHERE 
   EXISTS(
        SELECT 
           NULL
        FROM 
           [metadata]
        WHERE 
              ([propertyid] = '597ddddf-afd2-414f-9774-36f067038064' AND 
                [value] = N'moo') OR
              ([propertyid] = 'd83d12de-e4bc-4d18-be12-743504df3318' AND 
                [value] = N'foo') OR
              ([propertyid] = 'c00c3966-5034-4818-8567-abd660f37f15' AND 
                [value] = N'boo') AND 
              [File].[id] = [metadata].[fileid]
        GROUP BY 
           [fileid]
        HAVING 
           COUNT(*) = 3
       )
0 голосов
/ 22 апреля 2011

Я, возможно, что-то упускаю, но если вы хотите, чтобы все 3 условия были выполнены, почему бы просто не использовать «И» каждый раз вместо подсчета количества установленных свойств? Вы избежите группировки, в которой нет необходимости.

Я напишу:

    SELECT [uri] FROM [file] 
    WHERE EXISTS ( SELECT [fileid] FROM [metadata]
           WHERE [propertyid] = '597ddddf-afd2-414f-9774-36f067038064'
             AND [value] = N'moo'
             AND [propertyid] = 'd83d12de-e4bc-4d18-be12-743504df3318' 
             AND [value] = N'foo'
             AND [propertyid] = 'c00c3966-5034-4818-8567-abd660f37f15'
             AND [value] = N'boo'
             AND [file].[id] = [metadata].[fileid])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...