我在SQL Server中有一个历史表,它基本上通过一个进程跟踪一个项目。该项目有一些固定的字段,在整个过程中不会发生变化,但还有一些其他字段,包括状态和Id,随着过程步骤的增加而增加。
基本上我想在给定批量参考的情况下检索每个项目的最后一步。所以,如果我做了
Select * from HistoryTable where BatchRef = @BatchRef
它将返回批次中所有项目的所有步骤 - 例如
Id Status BatchRef ItemCount 1 1 Batch001 100 1 2 Batch001 110 2 1 Batch001 60 2 2 Batch001 100
但我真正想要的是:
Id Status BatchRef ItemCount 1 2 Batch001 110 2 2 Batch001 100
编辑:Appologies - 似乎无法让TABLE标签与Markdown一起使用 - 按照字母的帮助,在预览中看起来很好
答案 0 :(得分:10)
假设表格中有一个标识栏......
select
top 1 <fields>
from
HistoryTable
where
BatchRef = @BatchRef
order by
<IdentityColumn> DESC
答案 1 :(得分:6)
很难理解你的餐桌设计 - 我认为这样你的分隔符。
处理此问题的基本方法是对固定字段进行GROUP BY,并为某些unqiue值选择MAX(或MIN)(日期时间通常很好)。在您的情况下,我认为 GROUP BY将是BatchRef和ItemCount,而Id将是您唯一的列。
然后,加入表格以获取所有列。类似的东西:
SELECT *
FROM HistoryTable
JOIN (
SELECT
MAX(Id) as Id.
BatchRef,
ItemCount
FROM HsitoryTable
WHERE
BacthRef = @batchRef
GROUP BY
BatchRef,
ItemCount
) as Latest ON
HistoryTable.Id = Latest.Id
答案 2 :(得分:1)
假设Item Ids递增编号:
--Declare a temp table to hold the last step for each item id
DECLARE @LastStepForEach TABLE (
Id int,
Status int,
BatchRef char(10),
ItemCount int)
--Loop counter
DECLARE @count INT;
SET @count = 0;
--Loop through all of the items
WHILE (@count < (SELECT MAX(Id) FROM HistoryTable WHERE BatchRef = @BatchRef))
BEGIN
SET @count = @count + 1;
INSERT INTO @LastStepForEach (Id, Status, BatchRef, ItemCount)
SELECT Id, Status, BatchRef, ItemCount
FROM HistoryTable
WHERE BatchRef = @BatchRef
AND Id = @count
AND Status =
(
SELECT MAX(Status)
FROM HistoryTable
WHERE BatchRef = @BatchRef
AND Id = @count
)
END
SELECT *
FROM @LastStepForEach
答案 3 :(得分:1)
SELECT id, status, BatchRef, MAX(itemcount) AS maxItemcount
FROM HistoryTable GROUP BY id, status, BatchRef
HAVING status > 1
答案 4 :(得分:0)
用WMD格式化数据来解密你的数据有点困难,但你可以在SQL 2005上使用常见的表表达式来获取所需的技巧:
with LastBatches as (
select Batch, max(Id)
from HistoryTable
group by Batch
)
select *
from HistoryTable h
join LastBatches b on b.Batch = h.Batch and b.Id = h.Id
或子查询(假设子查询中的分组工作 - 我不记得了我的头顶):
select *
from HistoryTable h
join (
select Batch, max(Id)
from HistoryTable
group by Batch
) b on b.Batch = h.Batch and b.Id = h.Id
编辑:我假设你想要每个批次的最后一项。如果你只需要一个批次,那么另一个答案(做一个前1和下降顺序)是要走的路。
答案 5 :(得分:0)
如前所述,您可能希望重新排序查询以在另一个方向对其进行排序,以便实际获取第一行。然后你可能想要使用像
这样的东西SELECT TOP 1 ...
如果您使用的是MSSQL 2k或更早版本,或者是SQL兼容的版本
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY key ASC) AS rownumber,
columns
FROM tablename
) AS foo
WHERE rownumber = n
用于任何其他版本(或支持标准表示法的其他数据库系统)或
SELECT ... LIMIT 1 OFFSET 0
对于没有标准SQL支持的其他一些变体。
有关选择行的一些其他讨论,另请参阅this问题。使用聚合函数max()可能会也可能不会更快,具体取决于计算值是否需要表扫描。