الحصول على العنصر الأخير في الجدول - SQL
-
09-06-2019 - |
سؤال
لدي جدول محفوظات في SQL Server يتتبع بشكل أساسي عنصرًا من خلال العملية.يحتوي العنصر على بعض الحقول الثابتة التي لا تتغير طوال العملية، ولكنه يحتوي على بعض الحقول الأخرى بما في ذلك الحالة والمعرف والتي تتزايد مع زيادة خطوات العملية.
أريد في الأساس استرداد الخطوة الأخيرة لكل عنصر يتم إعطاؤه مرجع دفعة.لذلك إذا قمت بذلك
Select * from HistoryTable where BatchRef = @BatchRef
سيعيد جميع الخطوات لجميع العناصر الموجودة في الدفعة - على سبيل المثال
حالة المعرف BatchRef ItemCount 1 1 Batch001 100 1 2 Batch001 110 2 1 Batch001 60 2 2 Batch001 100
لكن ما أريده حقاً هو:
حالة المعرف BatchRef ItemCount 1 2 Batch001 110 2 2 Batch001 100
يحرر:Appologies - لا يبدو أن علامات TABLE تعمل مع Markdown - اتبعت المساعدة حرفيًا، ويبدو جيدًا في المعاينة
المحلول
من الصعب نوعًا ما أن تفهم تصميم طاولتك - أعتقد أنك أكلت المحددات الخاصة بك.
الطريقة الأساسية للتعامل مع ذلك هي التجميع حسب الحقول الثابتة، وتحديد الحد الأقصى (أو الحد الأدنى) لبعض القيم الفريدة (عادةً ما يعمل التاريخ والوقت بشكل جيد).في حالتك، أنا يفكر أن 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
نصائح أخرى
بافتراض أن لديك عمود هوية في الجدول ...
select
top 1 <fields>
from
HistoryTable
where
BatchRef = @BatchRef
order by
<IdentityColumn> DESC
بافتراض أن معرفات العناصر مرقمة بشكل متزايد:
--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
من الصعب بعض الشيء فك تشفير بياناتك بالطريقة التي قامت بتنسيقها 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 والترتيب التنازلي) هي الطريقة الصحيحة.
كما سبق أن اقترحت، ربما ترغب في إعادة ترتيب استعلامك لفرزه في الاتجاه الآخر بحيث تقوم بالفعل بإحضار الصف الأول.إذن ربما ترغب في استخدام شيء مثل
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 القياسي.
أنظر أيضا هذا سؤال لبعض المناقشات الإضافية حول اختيار الصفوف.قد يكون استخدام الدالة التجميعية max() أسرع أو لا يكون اعتمادًا على ما إذا كان حساب القيمة يتطلب فحصًا للجدول.