0

在我的数据库中,我有一个名为ThingsInACircle. 每次将 aThing添加到 时ThingsInACircle,都会添加一个ThingId自动递增的 a。

把这张表中的 想象Things成一个圆圈。
SELECT Thing FROM ThingsInACircle WHERE ThingId = 10旁边是
SELECT Thing FROM ThingsInACircle WHERE ThingId = 11
还有……
SELECT Thing FROM ThingsInACircle WHERE ThingId = min(ThingId)旁边
SELECT Thing FROM ThingsInACircle WHERE ThingId = max(ThingId)

我想说:对于给定的 ThingId 和偏移量,返回 ThingsInACircle 中从 ThingId 到 (ThingId + offset) 的所有记录(偏移量可能为负数)。

因此,以此为例进行设置:

以下是我们的 ThingId 列表:1 2 3 4 5 6 7 8 9

如果我想要 @ThingId = 2 和 @offset = 3 的所有 ThingId,则没有问题

SELECT ThingId FROM ThingsInACircle WHERE
ThingId BETWEEN @ThingId AND (@ThingId + @offset)

它会返回:2 3 4 5

但是,如果我想要 @ThingId = 8 和 @offset = 3 的所有 ThingId,那么就有问题了

该函数应返回:7 8 9 1

所以这是我的困境,我的数据访问层是否应该包含一个使用更复杂的存储过程的查询 (选择最小值、最大值并使用 if & else 来确定它们是否已被超过)来确定要检索哪些记录以进行处理记录被链接成一个圆圈?

或者业务逻辑层是否应该确定用户是否请求了超过 min 或 max 的 id + 偏移量,然后使用简单的 DAL 方法来完成它需要返回的内容?

这可能只是一个见仁见智的问题。前两天刚开始学习三层结构,是跟着微软教程学的,所以我想了解一下有些人认为DAL和BLL应该如何形成:如果DAL应该简单,BLL应该做所有的验证......或者反过来......或者我一起错过的东西。

4

3 回答 3

1
SELECT ThingId FROM ThingsInACircle 
WHERE
   ThingId BETWEEN @ThingId AND (@ThingId + @offset) 
   OR 
   ThingID BETWEEN 1 AND (@ThingID + @Offset - @MaxID)

@MaxID is the maximum thing id (end of the circle).

You have two cases:

normal case is when you have no overflow on offset. This is covered entirely by the second between.

second case is when you have an overflow, and you need to apply the offset over the boundary. In this case you have the range @ThingID - @ThingID + @offset, handled by the first BETWEEN, and 1 - ((@ThingID + @offset) - @MaxID), handled by the second BETWEEN.

If offset is higher than @MaxID, then all the @ThingIDs have to be considered, and this case is also covered by the second between.

于 2009-06-20T21:30:39.700 回答
0

大多数时候(在这种情况下),我建议从业务层中的业务逻辑开始(即圆圈中的最后一件事紧挨着第一件事)。

这意味着至少进行两次查询。第一个获取您的 thingID 范围:

int maxThingId = // select max(thingId) 'maxThingId' from ThingsInACircle
int minThingId = // select min(thingId) in the same query

所以你的第二个查询通常是:

select thingId 
from ThingsInACircle 
where thingId > @lowerBound and thingId < @upperBound

其中参数被预先计算为:

int lowerBound = requestedThingId;
int upperBound = lowerBound + offset;

然后是第三个,如有必要:

if(upperBound > maxThingId) { 
  upperBound -= maxThingId - minThingId; 
  // third query:
  // select thingId from ThingsInACircle where thingId < @upperBound
}

如果您开始看到性能问题或数据完整性等问题,您仍然可以考虑将此逻辑移至 DAL。

于 2009-06-20T22:11:03.237 回答
0

我通常发现这些比 DAL 更容易在其他地方处理,尤其是在处理 RDBMS 时。其他类型的集合抽象(数组、集合、字典等)将更容易使用。

于 2009-06-20T21:57:45.167 回答