Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
T-SQL:按组成员查找组_Sql_Tsql - Fatal编程技术网

T-SQL:按组成员查找组

T-SQL:按组成员查找组,sql,tsql,Sql,Tsql,给定SQL Server 2005中的以下两个表: IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'GroupItems') DROP TABLE GroupItems; CREATE TABLE GroupItems ( RowID INT IDENTITY(1,1) PRIMARY KEY , GroupID CHAR(1) , ItemID INT ); IF E

给定SQL Server 2005中的以下两个表:

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'GroupItems')
    DROP TABLE GroupItems;
CREATE TABLE GroupItems (
    RowID INT IDENTITY(1,1) PRIMARY KEY
    , GroupID CHAR(1)
    , ItemID INT
);

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'ItemList')
    DROP TABLE ItemList;
CREATE TABLE ItemList (
    ItemID INT PRIMARY KEY
)


INSERT GroupItems ( GroupID, ItemID )
SELECT 'A', 1
UNION SELECT 'A', 2
UNION SELECT 'A', 3
UNION SELECT 'A', 4
UNION SELECT 'B', 1
UNION SELECT 'B', 2
UNION SELECT 'B', 4
UNION SELECT 'C', 1
UNION SELECT 'C', 2
UNION SELECT 'D', 1
UNION SELECT 'D', 4
UNION SELECT 'D', 5


INSERT ItemList ( ItemID )
SELECT 1
UNION SELECT 2
UNION SELECT 4
我试图从表GroupItems中查找GroupId,其中ItemId与表ItemList的内容完全匹配

在样本数据中,结果应为“B”组

组A被拒绝,因为它包含不在ItemList表中的项

组C被拒绝,因为它不包含ItemList表中的所有项

D组由于两个原因被拒绝

目前,我正在做类似的事情

DECLARE @ListCount INT;
SELECT @ListCount = COUNT(*) FROM ItemList;

SELECT GI.GroupID FROM GroupItems AS GI
INNER JOIN ItemList AS IL ON IL.ItemID = GI.ItemID
INNER JOIN ( SELECT GroupID FROM GroupItems 
             GROUP BY GroupID
             HAVING COUNT(*) = @ListCOunt ) AS GS ON GS.GroupID = GI.GroupID  
GROUP BY GI.GroupID 
HAVING COUNT(*) = @ListCount;
这个函数给出了我正在寻找的正确结果,但是,在我的生产环境中,GroupItems表有数十万行和数千个唯一的GroupID。ItemList表通常包含十几行。此函数被相当定期地调用。我正在寻找一种更有效的方法来获得相同的结果。

假设:

没有相关信息缺失 ItemID是PKs,因此是唯一的 您不需要重复组/项组合的GroupID 这应该起作用:

select GroupID
from GroupItems
inner join ItemMaster
    on GroupItems.ItemID = ItemMaster.ItemID
inner join GroupMaster
    on GroupItems.GroupID = GroupMaster.GroupID
group by GroupID
having count(*) = (select count(*) from ItemList)
如果保证GroupItems具有唯一的组/项组合,则无需联接。

假设:

ItemID值只能大于0
您是否考虑过创建索引视图来聚合GroupItems的计数

CREATE VIEW GroupCounts (groupId, GroupCount) with SCHEMABINDING
AS
SELECT groupId, COUNT_BIG(1) /* I use 1 instead of asterisk by convention */
FROM GroupItems
GROUP BY groupId

CREATE CLUSTERED INDEX IX_GroupCounts on GroupCounts(groupId)
这样,您可以使用与现有查询类似的查询,但它应该具有更好的性能

SELECT GS.groupId FROM GroupItems AS GI
INNER JOIN ItemList AS IL ON IL.ItemID = GI.ItemID
INNER JOIN GroupCounts AS GS ON GS.GroupID = GI.GroupID  
GROUP BY GS.GroupID 
HAVING COUNT(1) = groupCount;

此解决方案返回A和B,其中一个不起作用。在样本数据上,它返回A和B。只应返回B。在T-Sql中,COUNT函数通常需要一个参数*。我想我没有错过任何相关的东西。如果两个组包含与ItemList完全相同的项,那么它们都应该被返回。我现在看到了这一点-但是,在我看来,您的示例有一个不一致的地方导致了这一点。您在GroupItems中有一个ItemID,但在ItemList中不存在。这是预期的吗?这似乎违反了这些概念——尽管您没有明确列出它们,但如果我看到ItemList和GroupItems表,我希望GroupItems表与ItemList和GroupList之间存在外键关系。对此,我深表歉意。假设GroupItems表中的ItemID列和ItemList表中的ItemID都有第三个表ItemMaster的外键。GroupItems和ItemList表之间没有外键关系。GroupItems.ItemID的值通常不包含在ItemList表中。OK-2连接到ItemMaster,并猜测GroupMaster以确保每个组/项目组合只有一个条目,然后匹配计数。这应该行得通。有什么方法可以用来创建一种启发式方法,先找到一个小得多的列表,然后检查剩余值。任何关于ListItem表的特许权都会有所帮助,例如,如果给定的范围GroupID和ItemID值都不为null,则总是x个项目数或总是在x-y范围内。ItemList表中的值也是非空且唯一的。除此之外,我认为我无法对数据做出任何保证。在您的生产环境中,您是否试图使ItemList表中的所有十几行都匹配。基本上,itemlist提供了一种模式,您需要使用它,findItemID始终大于0。我没有考虑过使用左连接。我将试用它,看看它与我原来的函数相比性能如何。
SELECT GS.groupId FROM GroupItems AS GI
INNER JOIN ItemList AS IL ON IL.ItemID = GI.ItemID
INNER JOIN GroupCounts AS GS ON GS.GroupID = GI.GroupID  
GROUP BY GS.GroupID 
HAVING COUNT(1) = groupCount;