【问题标题】:Is there a (effective) way to get 5 records to the left and right of a specific record with Access SQL?是否有一种(有效的)方法可以使用 Access SQL 在特定记录的左侧和右侧获取 5 条记录?
【发布时间】:2016-02-03 08:13:52
【问题描述】:

正如标题所说,我正在尝试执行 SELECT 语句,其中我选择了 1 条特定记录(该人搜索的记录),但我也想获得 5 条记录(特定记录之前和之后的 5 条记录) ) 在特定搜索记录的右侧和左侧,同时将当前/焦点记录保留在搜索记录上。

记录 ID(他们在哪里搜索)由与数字结合的过期值组成。例如,在本月,第一个创建的记录看起来像 1602030001<-- Year(16), month (02), day (03) and first record (0001)。所以他们本月创建的第二个将是1602030002,以此类推。

因此,如果他们搜索记录 16020050(2 月的第 50 条记录),我想显示记录 16020044 到 16020055。

我已经做过这样的事情,但它有一个缺点: 获取搜索到的记录 (16020050) 并在 VBA 中设置一个最大和最小变量 (int) 以对搜索到的记录号执行 -5 和 + 5。然后使用这些变量来执行 SELECT,例如:

SELECT * FROM SearchRecord WHERE ID > MinVariable (16020044) AND ID < MaxVariable (16020055)

但是,这样做的缺点是,例如,当 2 月份只有 500 条记录时,例如 16020500,然后行军开始 (16030001),并且该人正在搜索 2 月份的第 500 条记录,它还会搜索不存在的记录t 存在(最多 505 个,而这 5 个已经在 3 月 --> 16030005)。

我不知道一种更有效/更智能的方法可以将这 5 条额外记录分配到每一方,并且还保持逻辑,如果您搜索特定月份中的最后一条记录,则右侧的 5 条记录将从下个月。

我希望这是有道理的;)

【问题讨论】:

    标签: sql vba ms-access


    【解决方案1】:

    对于名为 [MyTable] 的表

    ID
    --------
    16020493
    16020494
    16020495
    16020496
    16020497
    16020498
    16020499
    16020500
    16030001
    16030002
    16030003
    16030004
    16030005
    16030006
    16030007
    

    我们可以通过查询得到以ID=16020500为中心的范围的起始ID

    SELECT MIN(ID) AS StartID
    FROM
        (
            SELECT TOP 6 ID 
            FROM MyTable
            WHERE ID <= 16020500
            ORDER BY ID DESC
        )
    

    返回

    StartID
    --------
    16020495
    

    我们可以简单地将该查询用作查询的 WHERE 子句中的子查询,以返回 11 行(5 行之前 + 主要行 + 5 行之后):

    SELECT TOP 11 *
    FROM MyTable
    WHERE 
        ID >= (
            SELECT MIN(ID) AS StartID
            FROM
                (
                    SELECT TOP 6 ID 
                    FROM MyTable
                    WHERE ID <= 16020500
                    ORDER BY ID DESC
                )
        )
    ORDER BY ID
    

    返回

    ID
    --------
    16020495
    16020496
    16020497
    16020498
    16020499
    16020500
    16030001
    16030002
    16030003
    16030004
    16030005
    

    【讨论】:

      【解决方案2】:

      我不得不想象这不会很快,尽管这是一种考虑问题的相当优雅的方式。当top 不存在时,这种情况更为常见。初始过滤器应有助于将搜索限制在前两个月左右的 id 窗口内(假设一个月内总是至少有 5 条记录)。

      select *
      from SearchRecord sr1
      where
              id between [Id:] / 10000 * 10000 - 9999 and [Id:] / 10000 * 10000 + 10005 
          and (select count(*) from SearchRecord sr2 where sr2.id between sr1.id and [Id:]) <= 6
          and (select count(*) from SearchRecord sr3 where sr3.id between [Id:] and sr1.id) <= 6
      

      【讨论】:

        【解决方案3】:

        我试图模拟你的情况,我创建了一个表变量(你可以跳过这个你有你的表),我曾经做正确的陈述,但我不认为这是最好的优化陈述。无论如何,它适用于我的模拟表。

        DECLARE @SearchRecord TABLE (ID BIGINT)    
        
        DECLARE @i INT=1
        WHILE @i<=50
        BEGIN 
            INSERT INTO @SearchRecord SELECT 16020000+@i
            INSERT INTO @SearchRecord SELECT 16030000+@i
            SET @i=@i+1
        END
        

        --你的逻辑

        DECLARE @SearchedID INT= 16020050
        DECLARE @Minid INT
        DECLARE @Maxid INT
        DECLARE @NearID INT
        SET @i=0
        SET @NearID=@SearchedID
        WHILE @i>=-5
        BEGIN
            IF EXISTS (SELECT * FROM @SearchRecord WHERE id=@nearID)
            BEGIN
                set @minid=@nearID
                PRINT @minid
                SET @i=@i-1
            END
            SET @nearID=@nearID-1
        END
        SET @i=0
        SET @nearID=@SearchedID
        WHILE @i<=5
        BEGIN
            IF EXISTS (SELECT * FROM @SearchRecord WHERE id=@nearID)
            BEGIN
                set @maxid=@nearID
                PRINT @maxid
                SET @i=@i+1
            END
            SET @nearID=@nearID+1
        END
        
        SELECT * FROM @SearchRecord WHERE (ID BETWEEN @minid AND @maxid) OR id=@searchedID  ORDER BY id
        

        【讨论】:

        • 我认为这个问题是 Access 特有的,你的方法看起来像 Transact SQL。
        猜你喜欢
        • 2010-10-13
        • 2021-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多