SQL查询多对映射表,用于数据匹配输入值集

时间:2015-11-06 02:47:39

标签: sql sql-server many-to-many

好的,这个很快就变得复杂了。我有一个系统,可以收集给定机器的硬件规格。我将专注于GPU以保持简单。一台机器可以有任意数量的GPU,并且GPU(我根据型号存储)可以存在于多台机器中。

在顶部,我有MachineSpec表,其中包含SpecID和GPUConfigID(以及其他人,但我们忽略了这些)。此GPUConfigID是GPU_Map表中GPUConfigID的外键。 GPU_Map表包含ID,GPUConfigID和GPUID列。 GPUID链接到GPU表中的GPUID,其中包含GPUID,Model,Speed等。

所以这里有一个有效的" configs"在GPU_Map表中:

enter image description here 我目前对该表中的所有案例都有效,但有一点需要注意。像GPUConfigIDs 1和2这样的情况会强制它们的唯一性,所以如果我尝试添加一个GPUID为1和3的新配置,它就不会让我(这很好)。不幸的是,在同一个配置中添加一个重复的GPUID(如在GPUConfigIDs 3和4中)将把它注册为一个全新的配置,尽管它是相同的。

值得注意的是,插入此表只涉及GPUID。基本上,我有一个GPUID列表,我需要看看它们是否作为GPU_Map表中的配置存在。如果他们不这样做,那么创建配置。如果是,则返回GPUConfigID。

这是我目前的存储过程:

@IDList IntList READONLY, 
@ID int OUTPUT
AS
BEGIN
    BEGIN TRAN gpuconfigupdate
        DECLARE @Count INT
        SELECT @Count = (SELECT COUNT(*)
            FROM GPU_Map as Map1
                LEFT OUTER JOIN @IDList as ID1
                ON Map1.GPUID = ID1.Item
            GROUP BY Map1.GPUConfigID
            HAVING COUNT(Map1.GPUID) = (SELECT COUNT(Item) FROM @IDList)
                AND COUNT(ID1.Item) = (SELECT COUNT(Item) FROM @IDList))

        IF @Count IS NULL BEGIN
            INSERT INTO GPU_Map (GPUConfigID, GPUID) 
            SELECT ((SELECT MAX(GPUConfigID) FROM GPU_Map)+1), Item FROM @IDList
        END

        SELECT @ID = (SELECT GPUConfigID 
                        FROM GPU_Map as Map1
                            LEFT OUTER JOIN @IDList as ID1
                            ON Map1.GPUID = ID1.Item
                        GROUP BY Map1.GPUConfigID
                        HAVING COUNT(Map1.GPUID) = (SELECT COUNT(Item) FROM @IDList)
                            AND COUNT(ID1.Item) = (SELECT COUNT(Item) FROM @IDList))
    COMMIT TRAN gpuconfigupdate
END

另请注意我的用户定义类型IntList:

CREATE TYPE [dbo].[IntList] AS TABLE(
    [Item] [INT] NULL
);

注意:GPU_Map表之前有一个主键(GPUConfigID,GPUID),但在尝试在同一个配置中输入重复的GPUID时会抛出主键错误(如GPUConfigIDs 3和4)。这就是我创建ID列并将其设置为主键的原因,这使我了解了当前的情况。

1 个答案:

答案 0 :(得分:0)

来自未来的人们,欢欣鼓舞!因为我已经设法找到解决这个问题的方法。

有问题的查询就是这个:

SELECT COUNT(*)
    FROM GPU_Map as Map1
        LEFT OUTER JOIN @IDList as ID1
        ON Map1.GPUID = ID1.Item
    GROUP BY Map1.GPUConfigID
    HAVING COUNT(Map1.GPUID) = (SELECT COUNT(Item) FROM @IDList)
        AND COUNT(ID1.Item) = (SELECT COUNT(Item) FROM @IDList)

除了@IDList包含重复值(有效)的情况之外,它按预期工作。解决方案是将最后两行更改为:

    HAVING COUNT(Map1.RAMID) = COUNT(ID1.Item)
        AND COUNT(DISTINCT ID1.Item) = (SELECT COUNT(DISTINCT Item) FROM @IDList))

请注意,COMMIT之前OP中存储过程的最后两行也需要以相同的方式更改。