SQL Conundrum ، كيفية تحديد أحدث تاريخ للجزء ، ولكن صف واحد فقط لكل جزء (فريد)
-
01-10-2019 - |
سؤال
أحاول لف رأسي حول هذا الصباح.
أحاول أن أظهر inventory
حالة الأجزاء (لمنتجاتنا) ويصبح هذا الاستعلام معقدًا فقط إذا حاولت إعادة جميع الأجزاء.
اسمحوا لي أن أضعها:
- جدول واحد
inventoryReport
- لدي قائمة مميزة من الأجزاء X التي أرغب في عرضها ، والتي يجب أن تكون نتيجة X # من الصفوف (صف واحد لكل جزء يوضح أحدث إدخال المخزون).
- يتكون الجدول من إدخالات مؤرخة لتغييرات المخزون (لذلك أحتاج فقط إلى
LATEST
دخول التاريخ لكل جزء). - جميع البيانات الواردة في هذا الجدول المفرد ، لذلك لا يوجد أي صلة ضرورية.
حاليًا لجزء واحد ، يكون الأمر بسيطًا إلى حد ما ويمكنني إنجاز ذلك عن طريق القيام بـ SQL التالي (لإعطائك بعض الأفكار):
SELECT TOP (1) ldDate, ptProdLine, inPart, inSite, inAbc, ptUm, inQtyOh + inQtyNonet AS in_qty_oh, inQtyAvail, inQtyNonet, ldCustConsignQty, inSuppConsignQty
FROM inventoryReport
WHERE (ldPart = 'ABC123')
ORDER BY ldDate DESC
هذا يجعلني أعلى صف واحد ، بسيط جدًا لكل جزء ، ومع ذلك أحتاج إلى إظهار كل X (دعنا نقول 30 جزءًا). لذلك أنا بحاجة إلى 30 صفًا ، مع هذه النتيجة. بالطبع ، سيكون الحل البسيط هو حلقة X# من مكالمات SQL في الكود الخاص بي (ولكن سيكون مكلفًا) وسيكون ذلك كافياً ، لكن لهذا الغرض ، أود أن أعمل هذا SQL أكثر لتقليل مكالمات X# مرة أخرى إلى DB (إذا لم يكن الحاجة) وصولاً إلى استفسار واحد فقط.
من ما يمكنني رؤيته هنا ، أحتاج إلى تتبع أحدث تاريخ لكل عنصر بطريقة أو بأخرى أثناء البحث عن مجموعة النتائج الخاصة بي.
سأفعل في النهاية
WHERE ldPart in ('ABC123', 'BFD21', 'AA123', etc)
للحد من الأجزاء التي أحتاجها. آمل أن أكون قد أوضحت سؤالي بما فيه الكفاية. اسمحوا لي أن أعرف إذا كان لديك فكرة. لا أستطيع أن أفعل DISTINCT
نظرًا لأن الصفوف ليست هي نفسها ، يجب أن يكون التاريخ هو الأحدث ، وأحتاج إلى أقصى درجات من الصفوف X.
أفكار؟ انا عالق...
المحلول
تعديل: تأكد من اختبار أداء كل حل. كما أشار في هذا السؤال, ، قد تتفوق طريقة CTE باستخدام ROW_Number.
;with cteMaxDate as (
select ldPart, max(ldDate) as MaxDate
from inventoryReport
group by ldPart
)
SELECT md.MaxDate, ir.ptProdLine, ir.inPart, ir.inSite, ir.inAbc, ir.ptUm, ir.inQtyOh + ir.inQtyNonet AS in_qty_oh, ir.inQtyAvail, ir.inQtyNonet, ir.ldCustConsignQty, ir.inSuppConsignQty
FROM cteMaxDate md
INNER JOIN inventoryReport ir
on md.ldPart = ir.ldPart
and md.MaxDate = ir.ldDate
نصائح أخرى
SELECT *
FROM (SELECT i.*,
ROW_NUMBER() OVER(PARTITION BY ldPart ORDER BY ldDate DESC) r
FROM inventoryReport i
WHERE ldPart in ('ABC123', 'BFD21', 'AA123', etc)
)
WHERE r = 1
تحتاج إلى الانضمام إلى مسابقة فرعية:
SELECT i.ldPart, x.LastDate, i.inAbc
FROM inventoryReport i
INNER JOIN (Select ldPart, Max(ldDate) As LastDate FROM inventoryReport GROUP BY ldPart) x
on i.ldPart = x.ldPart and i.ldDate = x.LastDate