我有三个表(至少是类似的),具有以下关系:
项目表:
ID | Val
---------+---------
1 | 12
2 | 5
3 | 22
组表:
ID | Parent | Range
---------+---------+---------
1 | NULL | [10-30]
2 | 1 | [20-25]
3 | NULL | [0-15]
GroupToItem表:
GroupID | ItemID
---------+---------
1 | 1
1 | 3
现在我想使用相同的查询向GroupToItem表添加第2组和第3组的行(因为此处未显示的其他一些条件更复杂)。我想限制我搜索的项目,如果新组有父项,但是如果没有,则查看所有项目。
目前我在两个几乎完全相同的语句上使用IF / ELSE,但是当父项存在时添加另一个JOIN行。是否可以进行连接以减少要查看的项目数量,只有在可以限制的情况下?
我的两个问题如下:
DECLARE @GroupID INT = 2;...
INSERT INTO GroupToItem(GroupID, ItemID)
SELECT g.ID,
i.ID,
FROM Group g
JOIN Item i ON i.Val IN g.Range
JOIN GroupToItem gti ON g.Parent = gti.GroupID AND i.ID = gti.ItemID
WHERE g.ID = @GroupID
-
DECLARE @GroupID INT = 3;...
INSERT INTO GroupToItem(GroupID, ItemID)
SELECT g.ID,
i.ID,
FROM Group g
JOIN Item i ON i.Val IN g.Range
WHERE g.ID = @GroupID
所以基本上我只想在给定的组有父级的情况下进行第二次JOIN。这可能在一个查询中吗?重要的是,与范围进行比较的项目数量尽可能小,因为对我来说这是一项密集的操作。
编辑:这似乎已经在这个测试设置中解决了它,类似于Denis Valeev的建议。如果我可以使用我的实时数据,我会接受。我一直有一些奇怪的问题 - 可能会出现更多问题。SELECT g.Id,
i.Id
FROM Group g
JOIN Item i ON (i.Val > g.Start AND i.Val < g.End)
WHERE g.Id = 2
AND (
(g.ParentId IS NULL)
OR
(EXISTS(SELECT 1 FROM GroupToItem gti WHERE g.ParentId = gti.GroupId AND i.Id = gti.ItemId))
)
答案 0 :(得分:1)
试试这个:
INSERT INTO GroupToItem(GroupID, ItemID)
SELECT g.ID,
i.ID,
FROM Group g
JOIN Item i ON i.Val IN g.Range
WHERE g.ID = @GroupID
and (g.ID in (3) or exists (select top 1 1 from GroupToItem gti where g.Parent = gti.GroupID AND i.ID = gti.ItemID))
答案 1 :(得分:0)
如果Range列是varchar数据类型,您可以尝试这样的事情:
INSERT INTO GROUPTOITEM (GROUPID, ITEMID)
SELECT A.ID, B.ID
FROM GROUP AS A
LEFT JOIN ITEM AS B
ON B.VAL BETWEEN CAST(SUBSTRING(SUBSTRING(A.RANGE,1,CHARINDEX('-',A.RANGE,1)-1),2,10) AS INT)
AND CAST(REPLACE(SUBSTRING(A.RANGE,CHARINDEX('-',A.RANGE,1)+1,10),']','') AS INT)