从配置表中返回具有非唯一数据的唯一键值对,其中值基于其他列的值而被固有

时间:2014-10-20 23:11:55

标签: sql-server

我有一个配置表,其中包含key =>值对,其中键是非唯一的,具有以下结构:

CREATE TABLE config
(
    ID int IDENTITY(1,1) PRIMARY KEY,
    key varchar(255) NOT NULL,
    value text,
    siteID int FOREIGN KEY REFERENCES site(siteID),
    userID bigint FOREIGN KEY REFERENCES user(userID),
    version decimal(10,4)
)  

该表可以包含基于非唯一键关联的多个值。此外,任何键/值可能有多个版本。

我想为给定站点的给定用户选择一组唯一的键/值对,这些用户遵循以下继承规则: 1)当存在重复的,选定的记录时,需要返回最大键/值(例如,如果有两个值没有站点或用户信息,则需要返回与最高版本号关联的值,否则版本被忽略)。 2)全局值(没有站点或用户信息的值)被包含站点信息的值覆盖。 3)仅包含用户信息的值会覆盖仅包含站点信息的值 4)仅包含用户信息的值将被包含用户和站点信息的值覆盖

我一直在这样做,通过在多个查询中选择上述信息,如下所示(伪代码):

array1 = select key, value from config where userID is NULL and siteID is NULL and version = (select MAX(c.version) from config c where c.name = name)
array2 = select top 1  key, value from config where userID is NULL and siteID = @siteID and version = (select MAX(c.version) from config c where c.name = name)
array3 = select top 1  key, value from config where userID = @userID and siteID is NULL and version = (select MAX(c.version) from config c where c.name = name)
array4 = select top 1  key, value from config where userID = @userID and siteID = @siteID and version = (select MAX(c.version) from config c where c.name = name)

然后我获取数据数组并执行以下操作:

$finalArray = array();
foreach($array1 as $row){
    $key = $row['key'];
    $value = $row['value'];
    $finalArray[$key] = $value;
}

foreach($array2 as $row){
    $key = $row['key'];
    $value = $row['value'];
    $finalArray[$key] = $value;
}
...etc.

这给了我想要的东西,但我必须认为有更好的方法......任何人都有任何好主意吗?

1 个答案:

答案 0 :(得分:0)

这样的事可能吗?

DECLARE @config TABLE
(
    ID int,
    [key] varchar(255) NOT NULL,
    value varchar(10),
    siteID int,
    userID int,
    [version] INT
);

declare @userID INT = 1;

INSERT INTO @config 
(ID, [key],[value],[siteID],userID,[version])
VALUES
--Global Values
(1, 'a','a',NULL,NULL,1),
(2, 'a','b',NULL,NULL,2),
(3, 'b','c',NULL,NULL,1),
--User values Site A
(4,'x','x',1,1,1),
(5,'x','z',1,1,2),
(6,'a','z',1,1,1),
(7,'xz','xz',1,1,1),
(8,'xz','xz',1,2,1),
(9,'b','d',1,2,1);

select
*
from @config

select
*
from (
    select
    ROW_NUMBER() OVER (
        PARTITION BY
            [key]
        ORDER BY
            ISNULL(siteID,-1) DESC,
            [version] DESC
    ) i,
    *
    from @config
    where
        ISNULL(userID,@userID) = @userID
) T
where
    i = 1