我有以下简化架构:
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]
FK到[file].[id]
和[propertyid]
FK到[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
)
我可以做得更好吗?
答案 0 :(得分:6)
;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)
)
答案 1 :(得分:2)
也许是这样的?
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
)
答案 2 :(得分:0)
我可能会遗漏一些东西,但是如果你想要满足所有3个条件,为什么不每次只使用“AND”而不是计算属性集的数量?您将避免不必要的GROUPING。
我会写:
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])