Sql 并且它在(MachineID,LogTime DESC)上有索引。使用ROW\u NUMBER的解决方案将扫描整个表(或仅扫描索引,但将是完全扫描)。如果索引在(MachineID,logtimeasc)上,它也会进行额外昂贵的排序。另一方面,假设您有一个

Sql 并且它在(MachineID,LogTime DESC)上有索引。使用ROW\u NUMBER的解决方案将扫描整个表(或仅扫描索引,但将是完全扫描)。如果索引在(MachineID,logtimeasc)上,它也会进行额外昂贵的排序。另一方面,假设您有一个,sql,sql-server,Sql,Sql Server,并且它在(MachineID,LogTime DESC)上有索引。使用ROW\u NUMBER的解决方案将扫描整个表(或仅扫描索引,但将是完全扫描)。如果索引在(MachineID,logtimeasc)上,它也会进行额外昂贵的排序。另一方面,假设您有一个小表Machines,其中有10行,每个MachineID对应一行。你将如何编写查询,在索引上执行10次搜索,而不是扫描整个大表?很酷的故事,@VladimirBaranov。如果您有一个更好的解决方案满足要求,但没有进行您所指出的扫描,请将其


并且它在
(MachineID,LogTime DESC)
上有索引。使用
ROW\u NUMBER
的解决方案将扫描整个表(或仅扫描索引,但将是完全扫描)。如果索引在
(MachineID,logtimeasc)
上,它也会进行额外昂贵的排序。另一方面,假设您有一个小表
Machines
,其中有10行,每个
MachineID
对应一行。你将如何编写查询,在索引上执行10次搜索,而不是扫描整个大表?很酷的故事,@VladimirBaranov。如果您有一个更好的解决方案满足要求,但没有进行您所指出的扫描,请将其作为答案发布。@BenThul,我添加了一个比较两个解决方案的答案。好极了,你是best@GuyCohen,我们不应该在另一个答案下写评论,但如果你觉得我的答案有用,你可以投票表决,因此,它离顶端越来越近,将来有更多的人有机会看到它。此外,您可以接受其中一个答案,向其他人展示什么答案对您最有用。
--drop table #tmp
SELECT  *
into #tmp
FROM    
(
select 1 as MachineLogID, 1 as MachineID , GETDATE() - 0.1 LogTime
    UNION
select 2 as MachineLogID, 1 as MachineID , GETDATE()- 0.2 LogTime
    UNION
select 3 as MachineLogID, 1 as MachineID , GETDATE()- 0.3 LogTime
    UNION
select 4 as MachineLogID, 1 as MachineID , GETDATE()- 0.4 LogTime
    UNION
select 5 as MachineLogID, 1 as MachineID , GETDATE()- 0.5 LogTime
    UNION
select 6 as MachineLogID, 1 as MachineID , GETDATE() - 0.6 LogTime
    UNION
select 7 as MachineLogID, 2 as MachineID , GETDATE()- 0.7 LogTime
    UNION
select 8 as MachineLogID, 2 as MachineID , GETDATE() - 0.8 LogTime
    UNION
select 9 as MachineLogID, 2 as MachineID , GETDATE() - 0.9 LogTime
    UNION
select 10 as MachineLogID, 2 as MachineID , GETDATE() - 0.10 LogTime
    UNION
select 11 as MachineLogID, 2 as MachineID , GETDATE() - 0.11 LogTime
    UNION
select 12 as MachineLogID, 2 as MachineID , GETDATE() - 0.12 LogTime
) a

SELECT  *
FROM    
(
    SELECT  top 5 *
    FROM  #tmp a
    where machineId = 1
    order by LogTime desc
        union
    SELECT  top 5 *
    FROM  #tmp a
    where machineId = 2
    order by LogTime desc
) a
order by a.machineId , a.LogTime desc
SELECT MachineLogID, MachineID, LogTime FROM tblMachineLogs WHERE MachineID='str_machineid' ORDER BY LogTime DESC LIMIT 5;
SELECT MachineLogID,
        MachineID,
        LogTime
FROM   (SELECT Row_number()OVER(partition BY MachineID ORDER BY LogTime DESC) Rn,
                MachineLogID,
                MachineID,
                LogTime
        FROM   tblMachineLogs) a
WHERE  rn <= 5 
Select top 5 * from yourTable where machineId =1
Union all
Select top 5 * from yourtable where machineid =2
Union all
.
.
.
.
Select top 5 * from yoyrtable 
Where machineid=10
CREATE TABLE [dbo].[Machines](
    [ID] [int] NOT NULL,
CONSTRAINT [PK_Machines] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

INSERT INTO [dbo].[Machines]
([ID])
VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
;
CREATE TABLE [dbo].[MachineLogs](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [MachineID] [int] NOT NULL,
    [LogTime] [datetime] NOT NULL,
 CONSTRAINT [PK_MachineLogs] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

CREATE NONCLUSTERED INDEX [IX_MachineID_LogTime] ON [dbo].[MachineLogs]
(
    [MachineID] ASC,
    [LogTime] DESC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

ALTER TABLE [dbo].[MachineLogs]  WITH CHECK ADD  CONSTRAINT [FK_MachineLogs_Machines] FOREIGN KEY([MachineID])
REFERENCES [dbo].[Machines] ([ID])
GO

ALTER TABLE [dbo].[MachineLogs] CHECK CONSTRAINT [FK_MachineLogs_Machines]
GO
WITH
CTE_Times
AS
(
    -- generate 100,000 rows with random datetimes between 2001-01-01 and ~2004-03-01 (100,000,000 seconds)
    SELECT TOP(100000)
        DATEADD(second, 100000000 * (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5), '20010101') AS LogTime
    FROM
        sys.all_objects AS X1
        CROSS JOIN sys.all_objects AS X2
)
-- generate 1M rows
INSERT INTO dbo.MachineLogs
    (MachineID
    ,LogTime)
SELECT
    dbo.Machines.ID
    ,CTE_Times.LogTime
FROM
    dbo.Machines
    CROSS JOIN CTE_Times
;
WITH
CTE_rn
AS
(
    SELECT
        ROW_NUMBER() OVER (PARTITION BY MachineID ORDER BY LogTime DESC) AS rn
        ,ID
        ,MachineID
        ,LogTime
    FROM MachineLogs
)
SELECT
    ID
    ,MachineID
    ,LogTime
FROM CTE_rn
WHERE rn <= 5
;
SELECT
    CA.ID
    ,CA.MachineID
    ,CA.LogTime
FROM
    Machines
    CROSS APPLY
    (
        SELECT TOP(5)
            MachineLogs.ID
            ,MachineLogs.MachineID
            ,MachineLogs.LogTime
        FROM MachineLogs
        WHERE
            MachineLogs.MachineID = Machines.ID
        ORDER BY LogTime DESC
    ) AS CA
;
SET STATISTICS IO ON;
(50 row(s) affected)
Table 'MachineLogs'. Scan count 1, logical reads 2365, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(50 row(s) affected)
Table 'MachineLogs'. Scan count 10, logical reads 30, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Machines'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.