我有一个SQL问题,我经常遇到反对,通常只是用嵌套查询来解决。我希望有人能提出更优雅的解决方案。
我经常需要为用户选择一个结果集,条件是它是最新的,或者是最大的或者其他什么。
例如:他们创建了完整的页面列表,但我只想要他们应用于页面的最新名称。碰巧的是,数据库包含每个页面的许多条目,并且只需要最新的条目。
我一直在使用嵌套的选择:
SELECT pg.customName, pg.id
FROM (
select id, max(createdAt) as mostRecent
from pages
where userId = @UserId
GROUP BY id
) as MostRecentPages
JOIN pages pg
ON pg.id = MostRecentPages.id
AND pg.createdAt = MostRecentPages.mostRecent
是否有更好的语法来执行此选择?
答案 0 :(得分:2)
看起来像你想要的
SELECT id, customname
FROM (SELECT id, customname,
row_number() OVER(PARTITION BY id ORDER BY createdat DESC) as pos
FROM pages
WHERE pages.userid = @UserId
) x
WHERE x.row_number = 1
(我假设您正在使用来自@UserId参数的SQL Server.row_number()将适用于SQL Server 2005,而上述内容也适用于Oracle,Postgresql 8.4 ...)
这将按用户ID选择所有页面,并计算最近使用排序的页面。另一种选择是:
SELECT id, (SELECT TOP 1 customname
FROM pages pages_inner
WHERE pages_inner.id = pages_outer.id
ORDER BY pages_inner.createdat DESC) as customname
FROM (SELECT DISTINCT id FROM pages WHERE pages.userid = @UserId) pages_inner
哪种方法更好取决于每个用户ID与每个用户ID的页数相比有多少页面行数,我猜。
答案 1 :(得分:1)
我不确定更好,但你可以尝试不同的语法
SELECT pg.customName, pg.id
FROM pages pg
WHERE userId = @UserId
AND NOT EXISTS
(
SELECT * FROM pages pg2
WHERE pg2.UserId = pg.UserId
AND pg2.id = pg.id
AND pg2.createdAt > pg.createdAt
)
另一种选择是外部加入,如Bill Karwin在这里的回答How to get all the fields of a row using the SQL MAX function?
答案 2 :(得分:1)
对于什么数据库(包括版本)?您发布的内容可能是MySQL,SQL Server或Sybase ......
使用:
SELECT pg.customName,
pg.id
FROM PAGES pg
JOIN (SELECT t.userid,
MAX(t.createdAt) as mostRecent
FROM PAGES t
GROUP BY t.userid) x ON x.id = pg.id
AND x.mostRecent = pg.createdAt
AND x.userid = @UserId
这是便携式查询的最佳方法,假设列引用正确。但是有限制数据集的替代方案 - SQL Server使用TOP
,MySQL / Postgre / SQLite使用LIMIT
,Oracle使用ROWNUM
。
什么是最好的取决于您的数据和&各个优化器如何看待它以及您的需求(可移动与否)。检查相应数据库的说明计划,以查看查询的效率。
答案 3 :(得分:0)
您使用的是Oracle吗?尝试查看使用分析函数的此查询是否适合您。 (现在不能访问db,所以无法测试自己。)
SELECT DISTINCT pg.id,
FIRST_VALUE(pg.customName) OVER (PARTITION BY pg.id ORDER BY pg.createdAt DESC) AS customName
FROM pages pg
答案 4 :(得分:0)
假设SQL Server和您的Pages表如下:
CREATE TABLE Pages (
Id int IDENTITY(1, 1) PRIMARY KEY
, CustomName nvarchar(20) NOT NULL
, CreatedAt datetime NOT NULL DEFAULT GETDATE()
, UserId int references Users(Id)
)
我会做以下事情:
select TOP 1 p.Id as PageId
, p.CustomName
from Pages p
where p.UserId = @UserId
order by p.Created desc
甚至:
select TOP 1 p.Id as PageId
, p.CustomName
, MAX(p.CreatedAt) DateTimeCreated
from Pages p
where p.UserId = @UserId
group by p.Id
, p.CustomName
我希望这有帮助! (如果没有,请提供进一步的详细信息,以便我们可以更好地帮助)
答案 5 :(得分:-1)
我不知道你的桌子是什么样的
Select top 1 pg.createdAt
,pg.customName
,pg.id
from table pg
where pg.UserId = @UserId
order by pg.createdAt Desc
我需要在您的桌子上提供更多信息