2011-04-22 50 views
5

我有以下簡化架構的行:TSQL查詢找到匹配的一組屬性

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] FKS到[file].[id][propertyid] FKS到[property].[id]。假設[properyid]CLUSTERED[value]NON-CLUSTERED

我想選擇所有匹配一定元數據集的文件;例如每個文件的屬性值對爲size = 1 Kbextension = '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

你用什麼版本的SQL Server? – abatishchev 2011-04-22 08:59:05

+0

我認爲我們支持所有版本回到2003年,包括快遞。 – briantyler 2011-04-22 11:51:20

+0

afaik,有2000年,然後是2005年 – abatishchev 2011-04-22 12:26:40

回答

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) 
) 
+0

這看起來可能有效,通常我已經看到這類問題通過爲每個要查找的屬性加入元數據表解決。 – HLGEM 2011-04-22 13:43:28

+0

乾杯,非常感謝。 – briantyler 2011-04-22 16:05:28

0

我也許錯過了一些東西,但是如果你希望滿足所有3個條件,那麼爲什麼不每次都使用「AND」而不是計算所設置的屬性數?你將避免一個不必要的分組。

我會寫:

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]) 
+0

我做'count',因爲我需要正好三行存在'metadata';每個鍵值對一個。內部查詢返回匹配任何鍵值對的所有行,然後外部查詢會說'只給出所有條件匹配的'fileid's'。你的查詢聲明在'metadata'中存在一行,其中'propertyid'和'value'每個同時有三個不同的值,因此它總是什麼都不會返回。順便說一下,三個屬性 - 值對是任意的,它可以是任意數字。 – briantyler 2011-04-22 12:06:41

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 
     ) 
相關問題