[英]How to find the *position* of a single record in a limited, arbitrarily ordered record set?
MySQL
假设您只想通过某个 id 检索单个记录,但您想知道如果您在一个大的有序集中遇到它,它的 position 会是什么。
一个典型的例子是照片库。 你登陆一张照片,但系统必须知道它在整个画廊中的偏移量是多少。
我想我可以使用自定义索引字段来跟踪位置,但是在 SQL 中必须有更优雅的方式。
因此,首先您创建一个虚拟表,其中 position # 按您的 ORDER BY 排序,然后您 select 是该集合中最高的一个。 那是更大结果集中的 position。 如果您不按唯一值/值集排序,您可能会遇到问题......
如果您在 (photo_gallery_id, date_created_on) 上创建索引,它可能会进行索引扫描(取决于照片的分布),这应该比表扫描更快(前提是您的 gallery_id 不是照片的 90% 或诸如此类) .
SELECT @row := 0;
SELECT MAX( position )
FROM ( SELECT @row := @row + 1 AS position
FROM photos
WHERE photo_gallery_id = 43
AND date_created_on <= 'the-date-time-your-photo-was'
ORDER BY date_created_on ) positions;
不需要额外的表,为什么不只计算记录呢?
您知道它们的显示顺序(可能会有所不同),但您知道这一点。
你也知道当前记录的ID; 假设它是在日期订购的:
记录的偏移量是日期<该日期的记录总数。
SELECT COUNT(1) FROM ... WHERE date < "the-date"
这为您提供了可以用作其他查询的偏移量的数字...
并不真地。 我认为 Oracle 给你一个“ROWID”或类似的东西,但大多数人不给你一个。 自定义排序,例如数据库中的一列,告诉您想要 position 画廊中的条目是好的,因为您永远无法确定 SQL 会按照您认为它们应该在的顺序将事物放入表中。
由于您不具体说明您使用的是什么数据库,因此您可以在 SQL Server 2005 中使用
SELECT
ROW_NUMBER() OVER (ORDER BY PhotoID)
, PhotoID
FROM dbo.Photos
您没有说您使用的是什么 DBMS,“解决方案”会相应地有所不同。 在 Oracle 中,您可以这样做(但我敦促您不要这样做:):
select photo, offset
from
( select photo
, row_number() over (partition by gallery_id, order by photo_seq) as offset
from photos
)
where id = 123
该查询将 select所有照片(全表扫描),然后挑选出您要求的照片 - 不是性能查询!
我建议如果您真的需要此信息,则应将其存储。
假设 position 完全由 id 决定,难道不就是把所有 id 值较小的记录都统计一下那么简单吗?:
select
po.[id]
...
((select count(pi.[id]) from photos pi where pi.[id] < po.[id]) + 1) as index
...
from photos po
...
我不确定这种查询的性能影响是什么,但我认为返回大量记录可能是一个问题。
您必须了解“应用程序密钥”和“技术密钥”之间的区别。
存在技术密钥的唯一目的是使项目独一无二。 它通常在 INTEGER 或 BIGINT 中,生成(身份等)。 该键用于定位数据库中的对象,快速找出已持久化的 object(ID 必须 > 0,因此默认 ID == 0 的 object 尚未在数据库中)等。
应用程序密钥是您需要在应用程序上下文中理解 object 的东西。 在这种情况下,它是图库中照片的排序。 这对数据库没有任何意义。
考虑有序列表:这是大多数语言的默认设置。 您有一组项目,由索引访问。 对于数据库,此索引是应用程序键,因为数据库中的集合是无序的(或者数据库不保证任何排序,除非您指定 ORDER BY)。 出于同样的原因,对查询结果进行分页非常痛苦:数据库真的不喜欢“位置”的概念。
因此,您必须做的是添加一个索引行(即 INTEGER 说明您的图像在图库中的哪个 position ;不是用于更快访问的数据库索引,即使您应该在此列上创建索引...)并维护那。 对于每次插入,您必须UPDATE index = index + 1 where index >= insertion_point
等。
是的,这很糟糕。 我知道的唯一解决方案:使用 ORM 框架为您解决这个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.