SQL通过非唯一字段查找下一条记录

时间:2009-12-10 15:33:17

标签: sql odbc

我需要找到一个数据库中的下一条记录(例如)给定的姓氏。因此,如果用户正在查看A Smith,则查询将返回Next A Smith或B Smith

解决方案可能类似于此处讨论的解决方案:selecting subsequent records arbitrarily with limit但使用符合ODBC 2.0的数据库而不是mysql。

目前我有程序解决方案,但速度很慢。是否有更优雅的方法只使用基本的SQL?

“适当”订单中的示例数据

recnum, surname, firstnames 
1000,smith,andrew 
1320,smith,andrew 
1340,smith,andrew 
14,smith,anton 
17,smith,anton 
2000,smith,brian 
2030,smith,brian 
1017,smith,brianally 

我会得到当前记录的公式,需要找到上面的下一个(在姓氏,名字,recnum上排序)在这个例子中1320的情况很简单,但1340使它更难!

4 个答案:

答案 0 :(得分:1)

SQL旨在使用并返回 set 数据。事实上,Coad(或其中一位关系主义大师)用来描述关系数据库的一点是没有“下一条记录” - 这个概念甚至不应该存在。

因此,从SQL的角度来看,您应该做的是创建一个包含所需数据的集合:

select * from YourTable
    where LastName = @whatever
    order by FirstName

然后,如果您希望一次处理一条记录,则可能需要将光标放入该数据集。使用它,您只需查看一条记录,当您将光标前进到下一条记录时,它将是下一条记录。

答案 1 :(得分:1)

根据您的示例数据并假设在流程中的任何时刻您都有可用于当前记录的“recnum”值,可以通过使用一系列最多三个查询来查询下一个值。如果您将三个数据(surname,firstname,recnum)视为复合索引,那么您希望按索引顺序查找下一个记录。因此,假设您拥有当前记录中的三个数据,请运行:

select top 1 surname, firstname, recnum from Table
    where surname = @CurrentLast and 
    firstname = @CurrentFirst and 
    Recnum > @CurrRec
    order by surname, firstname, recnum

如果是空的,那么运行:

select top 1 surname, firstname, recnum from Table
    where surname = @CurrentLast and 
    firstname > @CurrentFirst
    order by surname, firstname, recnum

最后,如果那是空的:

select top 1 surname, firstname, recnum from Table
    where surname > @CurrentLast
    order by surname, firstname, recnum

如果对三个字段编制索引,则应该合理有效。也可以使用单个查询,例如以下(语法可能错误),但它需要在所有三个字段上使用复合索引才能有效。

select top 1 surname, firstname, recnum from Table
    where surname+firstname+convert(recnum,char) > @CombinedValue
    order by surname, firstname, recnum

如果recnum引用基础数据中的物理记录号,并且当其他条件在排序中匹配时,如果SQL引擎使用记录号作为平局,那么我认为可以通过子句将recnum排除在顺序之外。

答案 2 :(得分:0)

如果用'next'表示名字的字母顺序, 然后尝试:

  Select * From Table T
  Where lastName = @GivenSurname
     And firstName = 
      (Select Min(FirstName)
       From Table 
       Where LastName = T.LastName
          And FirstName > @GivenFirstName)

如果可能有多个记录具有相同的名字和姓氏,并且您有代理主键,那么您可以使用以下方法任意选择其中一个:

  Select * From Table T1
  Where lastName = @GivenSurname
     And PK = 
      (Select Min(PK) From Table T2
       Where LastName = T1.LastName
         And FirstName =
          (Select Min(FirstName)
           From Table
           Where LastName = T1.LastName
                And FirstName > @GivenFirstName))

答案 3 :(得分:0)

“没有状态保存”是否意味着您根本无法存储任何数据,甚至是预先缓存?换句话说,查询

SELECT recnum FROM my_table ORDER BY surname, firstname

使用getrows将其存储在本地数组中。然后在每次执行预准备语句

时遍历该数组
SELECT surname, firstname FROM my_table WHERE recnum = ?

这几乎肯定会比一次查询所有内容慢,但它会满足你的目标。