SQL 查询多对多映射 table 以获得匹配输入值集的数据
SQL query many-many mapping table for data matching set of input values
好的,这个很快就变得复杂了。我有一个系统可以收集给定机器的硬件规格。为了简单起见,我将只关注 GPU。一台机器可以有任意数量的GPU,一个GPU(我是按型号存储的)可以存在于多台机器上。
在顶部我有一个 MachineSpec table,它包含一个 SpecID 和一个 GPUConfigID(以及其他但我们忽略它们)。此 GPUConfigID 是 GPU_Map table 中 GPUConfigID 的外键。 GPU_Map table 包含 ID、GPUConfigID 和 GPUID 列。 GPUID与GPU中的GPUID挂钩table,包含GPUID、Model、Speed等
这里是 GPU_Map table 中有效 "configs" 的示例:
我目前使用的方法适用于 table 中的所有情况,但有一个警告。 GPUConfigIDs 1 和 2 之类的情况将强制执行它们的唯一性,因此如果我尝试添加具有 GPUIDs 1 和 3 的新配置,它不会让我这样做(这很好)。不幸的是,在相同的配置中添加重复的 GPUID(如在 GPUConfigIDs 3 和 4 中)会将其注册为一个全新的配置,尽管它是相同的。
请务必注意,插入此 table 仅涉及 GPUID。基本上,我有一个 GPUID 列表,我需要查看它们是否作为配置存在于 GPU_Map table 中。如果他们不这样做,则创建配置。如果他们这样做,那么 return 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 table 之前的主键为 (GPUConfigID, GPUID),但在同一配置中尝试输入重复的 GPUID 时会抛出主键错误(例如GPUConfigIDs 3 和 4)。这就是我创建 ID 列并将其设置为主键的原因,这导致了我目前的情况。
来自未来的人们,欢欣鼓舞!因为我设法找到了解决这个问题的方法。
有问题的查询是这个:
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 中存储过程的最后两行也需要以相同的方式更改。
好的,这个很快就变得复杂了。我有一个系统可以收集给定机器的硬件规格。为了简单起见,我将只关注 GPU。一台机器可以有任意数量的GPU,一个GPU(我是按型号存储的)可以存在于多台机器上。
在顶部我有一个 MachineSpec table,它包含一个 SpecID 和一个 GPUConfigID(以及其他但我们忽略它们)。此 GPUConfigID 是 GPU_Map table 中 GPUConfigID 的外键。 GPU_Map table 包含 ID、GPUConfigID 和 GPUID 列。 GPUID与GPU中的GPUID挂钩table,包含GPUID、Model、Speed等
这里是 GPU_Map table 中有效 "configs" 的示例:
请务必注意,插入此 table 仅涉及 GPUID。基本上,我有一个 GPUID 列表,我需要查看它们是否作为配置存在于 GPU_Map table 中。如果他们不这样做,则创建配置。如果他们这样做,那么 return 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 table 之前的主键为 (GPUConfigID, GPUID),但在同一配置中尝试输入重复的 GPUID 时会抛出主键错误(例如GPUConfigIDs 3 和 4)。这就是我创建 ID 列并将其设置为主键的原因,这导致了我目前的情况。
来自未来的人们,欢欣鼓舞!因为我设法找到了解决这个问题的方法。
有问题的查询是这个:
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 中存储过程的最后两行也需要以相同的方式更改。