Frage

Ich habe eine Verlaufstabelle in SQL Server, die im Grunde ein Element durch einen Prozess verfolgt.Das Element verfügt über einige feste Felder, die sich im Laufe des Prozesses nicht ändern, verfügt jedoch über einige andere Felder, einschließlich Status und ID, die mit der Anzahl der Schritte des Prozesses inkrementiert werden.

Grundsätzlich möchte ich den letzten Schritt für jedes Element mit einer Batch-Referenz abrufen.Also, wenn ich ein mache

Select * from HistoryTable where BatchRef = @BatchRef

Es werden alle Schritte für alle Artikel im Stapel zurückgegeben, z. B

Id Status BatchRef ItemCount
1       1       Batch001        100
1       2       Batch001        110
2       1       Batch001        60
2       2       Batch001        100

Aber was ich wirklich will, ist:

Id Status BatchRef ItemCount
1       2       Batch001        110
2       2       Batch001        100

Bearbeiten:Entschuldigung – ich kann die TABLE-Tags anscheinend nicht mit Markdown zum Laufen bringen – habe die Hilfe genau befolgt und sieht in der Vorschau gut aus

War es hilfreich?

Lösung

Es ist ziemlich schwierig, das Design Ihrer Tabelle zu verstehen – ich denke, Ihre Trennzeichen sind SO übertrieben.

Die grundlegende Möglichkeit, dies zu handhaben, besteht darin, Ihre festen Felder nach GROUP BY zu gruppieren und einen MAX (oder MIN) für einen eindeutigen Wert auszuwählen (ein Datum/Uhrzeit-Wert funktioniert normalerweise gut).In Ihrem Fall ich denken dass das GROUP BY BatchRef und ItemCount wäre und Id Ihre eindeutige Spalte sein würde.

Verbinden Sie sich dann wieder mit der Tabelle, um alle Spalten zu erhalten.Etwas wie:

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

Andere Tipps

Angenommen, Sie haben eine Identitätsspalte in der Tabelle ...

select 
    top 1 <fields> 
from 
    HistoryTable 
where 
    BatchRef = @BatchRef 
order by 
    <IdentityColumn> DESC

Angenommen, die Artikel-IDs sind fortlaufend nummeriert:

--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
SELECT id, status, BatchRef, MAX(itemcount) AS maxItemcount 
FROM HistoryTable GROUP BY id, status, BatchRef 
HAVING status > 1 

Es ist etwas schwierig, Ihre Daten so zu entschlüsseln, wie WMD sie formatiert hat, aber Sie können mit gängigen Tabellenausdrücken in SQL 2005 den Trick anwenden, den Sie benötigen:

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

Oder eine Unterabfrage (vorausgesetzt, die Gruppierung nach in der Unterabfrage funktioniert – spontan weiß ich nicht mehr):

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

Bearbeiten:Ich ging davon aus, dass Sie den letzten Artikel wollten jeden Charge.Wenn Sie es nur für eine Charge benötigen, sind die anderen Antworten (Top 1 erstellen und absteigend ordnen) die richtige Wahl.

Wie bereits vorgeschlagen, möchten Sie Ihre Abfrage wahrscheinlich neu anordnen, um sie in die andere Richtung zu sortieren, sodass Sie tatsächlich die erste Zeile abrufen.Dann möchten Sie wahrscheinlich so etwas verwenden

SELECT TOP 1 ...

wenn Sie MSSQL 2k oder früher oder die SQL-kompatible Variante verwenden

SELECT * FROM (
  SELECT
    ROW_NUMBER() OVER (ORDER BY key ASC) AS rownumber,
    columns
  FROM tablename
) AS foo
WHERE rownumber = n

für jede andere Version (oder für andere Datenbanksysteme, die die Standardnotation unterstützen), oder

SELECT ... LIMIT 1 OFFSET 0

für einige andere Varianten ohne die Standard-SQL-Unterstützung.

Siehe auch Das Frage für eine zusätzliche Diskussion zum Auswählen von Zeilen.Die Verwendung der Aggregatfunktion max() kann schneller sein oder auch nicht, je nachdem, ob für die Berechnung des Werts ein Tabellenscan erforderlich ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top