LINQ to SQL:معقدة الاستعلام مع البيانات المجمعة عن تقرير من جداول متعددة على نظام الطلبات
-
21-08-2019 - |
سؤال
أريد تحويل الاستعلام التالي في LINQ الجملة.أواجه الكثير من المتاعب تمكنت من الحصول على عمل.أنا فعلا حاولت بدءا من LINQ ، ولكن وجدت أن قد يكون لديك أفضل حظا إذا كتبت بطريقة أخرى.
SELECT
pmt.guid,
pmt.sku,
pmt.name,
opt.color,
opt.size,
SUM(opt.qty) AS qtySold,
SUM(opt.qty * opt.itemprice) AS totalSales,
COUNT(omt.guid) AS betweenOrders
FROM
products_mainTable pmt
LEFT OUTER JOIN
orders_productsTable opt ON opt.products_mainTableGUID = pmt.guid
LEFT OUTER JOIN orders_mainTable omt ON omt.guid = opt.orders_mainTableGUID AND
(omt.flags & 1) = 1
GROUP BY
pmt.sku, opt.color, opt.size, pmt.guid, pmt.name
ORDER BY
pmt.sku
النتيجة النهائية هو الجدول الذي يظهر لي معلومات عن المنتج كما ترون أعلاه.كيف يمكنني كتابة هذا الاستعلام في LINQ شكل باستخدام الفهم syntax ؟
بالإضافة إلى ذلك, قد ترغب في إضافة عوامل تصفية إضافية (إلى orders_mainTable ، على سبيل المثال).
هنا هو مثال واحد حاولت أن تجعل العمل, و كانت قريبة إلى حد ما ولكن لست متأكدا إذا كان هذا هو "الصحيح" الطريقة, و لم يكن قادرا على الفريق أنه حسب الحجم و اللون من orders_productsTable.
from pmt in products_mainTable
let Purchases =
from opt in pmt.orders_productsTable
where ((opt.orders_mainTable.flags & 1) == 1)
where ((opt.orders_mainTable.date_completedon > Convert.ToDateTime("01/01/2009 00:00:00")))
select opt
orderby pmt.sku
select new {
pmt.guid,
pmt.sku,
pmt.name,
pmt.price,
AvgPerOrder = Purchases.Average(p => p.qty).GetValueOrDefault(0),
QtySold = Purchases.Sum(p => p.qty).GetValueOrDefault(),
SoldFor = Purchases.Sum(p => p.itemprice * p.qty).GetValueOrDefault()
}
*تحرير:
إلى أن يكون قليلا أكثر وضوحا حتى يمكنك فهم ما أحاول فعله هنا بعض مزيد من التوضيح.
يتم تخزين المنتجات في products_mainTable أوامر يتم تخزينها في orders_mainTable المنتجات التي تم طلبها يتم تخزينها في orders_productsTable
أريد إنشاء عدة تقارير على أساس المنتجات, أوامر, الخ.التنقيب في البيانات وإيجاد معنى بت العرض إلى المستخدم النهائي.
في هذه الحالة, أنا أحاول عرض المنتجات التي تم شراؤها على مدى فترة من الزمن, و هي الأكثر شعبية.كم بيعها بأي سعر و ما هو الاختراق في النظام.ربما ليس أفضل من النظام ، ولكن أنا مجرد تجارب و اختار هذا واحد.
جميع الجداول لها علاقات الجداول الأخرى.لذلك من الجدول المنتج يمكنني الحصول على أي أوامر طلب هذا المنتج ، إلخ.
أكبر مشكلة أعاني هو فهم كيف LINQ يعمل خصوصا مع تجميع البيانات المجمعة, ملحقات, الاستعلامات الفرعية ، إلخ.كان الأمر ممتعا لكنه بدءا من الحصول على محبطا لأنني أواجه صعوبة في العثور على توضيحات مفصلة حول كيفية القيام بذلك.
المحلول 2
برونو شكرا جزيلا على المساعدة الخاصة بك!على FirstOrDefault() ربما كان أكبر مساعدة.التالية بعض ما فعلت ، و مورد آخر خطرت التالية التي يبدو للعمل بشكل جميل!هذا استعلام LINQ أدناه أعطاني ما يقرب من الدقيق النسخ المتماثل في SQL أنا نشرت أعلاه.
وهنا الموارد الأخرى وجدت على القيام LEFT JOIN في LINQ: بلوق وظيفة
الجواب النهائي:
from pmt in products_mainTable
join opt in orders_productsTable on pmt.guid equals opt.products_mainTableGUID into tempProducts
from orderedProducts in tempProducts.DefaultIfEmpty()
join omt in orders_mainTable on orderedProducts.orders_mainTableGUID equals omt.guid into tempOrders
from ordersMain in tempOrders.DefaultIfEmpty()
group pmt by new { pmt.sku, orderedProducts.color, orderedProducts.size } into g
orderby g.FirstOrDefault().sku
select new {
g.FirstOrDefault().guid,
g.Key.sku,
g.Key.size,
QTY = g.FirstOrDefault().orders_productsTable.Sum(c => c.qty),
SUM = g.FirstOrDefault().orders_productsTable.Sum(c => c.itemprice * c.qty),
AVG = g.FirstOrDefault().orders_productsTable.Average(c => c.itemprice * c.qty),
Some = g.FirstOrDefault().orders_productsTable.Average(p => p.qty).GetValueOrDefault(0),
}
نصائح أخرى
وأنا أيضا مبتدئا في LINQ. أنا لا أعرف إذا كان هذا هو الطريق الصحيح للتجمع من قبل العديد من المجالات ولكن اعتقد ان لديك لتحويل هذه المجالات تضم إلى مفتاح تمثل. لذلك، على افتراض أن جميع الحقول التجمع الخاص بك هي سلاسل أو [إينتس] يمكنك جعل مفتاح كما يلي:
var qry = from pmt in products_mainTable
join opt in orders_productsTable on pmt.guid equals opt.products_mainTableGUID
join omt in orders_mainTable on opt.orders_mainTableGUID equals omt.guid
where (opt.orders_mainTable.flags & 1) == 1
group omt by pmt.sku + opt.price + opt.size + pmt.guid + pmt.name into g
orderby g.sku
select new
{
g.FirstOrDefault().guid,
g.FirstOrDefault().sku,
g.FirstOrDefault().name,
g.FirstOrDefault().color,
g.FirstOrDefault().price,
AvgPerOrder = g.Average(p => p.qty).GetValueOrDefault(0),
QtySold = g.Sum(p => p.qty).GetValueOrDefault(),
SoldFor = g.Sum(p => p.itemprice * p.qty).GetValueOrDefault()
};
لم أكن اختبار هذا لذا يرجى معرفة ما اذا كان هذا يساعدك بأي شكل من الأشكال.
وكان هذا مفيدا جدا بالنسبة لي الشكر. كان لي كانت مشكلة مشابهة كنت أحاول لفرز من خلال فقط حالتي أبسط من ذلك بكثير وأنا لم يكن لدي أي ينضم فيها. كنت مجرد محاولة لتجميع حقل واحد، الحصول على الحد الأدنى من آخر، والفرز. (دقيقة والفرز في نفس الاستعلام)
وهنا هو SQL أردت أن إعادة في جملة ينق:
select t.Field1, min(t.Field2), COUNT(*)
from SomeTable t
group by t.Field1
order by t.Field1
وبفضل مشاركتك تمكنت في نهاية المطاف من أجل التوصل إلى هذا:
from t in SomeTable
group t by new { t.Field1 } into g
orderby g.Key.Field1
select new
{
g.Key.Field1,
code = g.Min(c => c.Field2),
qty = g.Count()
}
ما يخلق SQL التالية وراء الكواليس:
SELECT [t1].[Field1], [t1].[value] AS [code], [t1].[value2] AS [qty]
FROM (
SELECT MIN([t0].[Field2]) AS [value], COUNT(*) AS [value2], [t0].[Field1]
FROM [SomeTable] AS [t0]
GROUP BY [t0].[Field1]
) AS [t1]
ORDER BY [t1].[Field1]
والكمال، بالضبط ما كنت أبحث القيام به. وكان المفتاح للي أنك أظهرت أنه من الممكن القيام بذلك داخل الجديد {} وهو أمر كنت قد فكرت أبدا في محاولة. هذا هو ضخم، وأنا الآن أشعر أنني لديهم فهم أفضل بكثير في المستقبل.