sql - एकाधिक शामिल होने, गिनने और बाएं जुड़ने के लिए LINQ LINQ



join left-join (1)

मैंने यह SQL अनुरोध कई JOIN (एक LEFT JOIN सहित) के साथ लिखा था।
यह मुझे अपेक्षित परिणाम देता है

SELECT DISTINCT c.Id, 
       c.Title, 
       COUNT(v.Id) AS 'Nb_V2',
       COUNT(DISTINCT v.IdUser) AS 'Nb_V1',
       r.cnt AS 'Nb_R'
FROM TABLE_C c
JOIN TABLE_V v on c.Id = v.Id
LEFT JOIN ( 
    SELECT Id, COUNT(*)  AS cnt 
    FROM TABLE_R 
    GROUP BY Id
) r ON c.Id = r.Id
WHERE c.IdUser = '1234'
GROUP BY c.Id, c.Title, r.cnt

हालांकि, 'इस अनुरोध के बराबर लाइनक के रूप में आईडी, इसे मेरे आवेदन की डेटा एक्सेस परत में डालने के लिए।

मैंने कुछ इस तरह की कोशिश की:

var qResult = from c in dbContext.TABLE_C
              join v in dbContext.TABLE_V on c.IdC equals v.IdC
              join r in dbContext.TABLE_R on v.IdC equals r.IdC into temp
              from x in temp.DefaultIfEmpty()
              group x by new { c.IdC, c.Title /*miss something ?*/} into grouped
              select new
              {
                  IdC = grouped.Key.IdC,          --good result
                  Title = grouped.Key.Title,      --good result
                  NbR = grouped.Distinct().Count(t => t.IdC > 0), --good, but "t.Id > 0" seems weird
                  Count = --I'm lost. No idea how to get my COUNT(...) properties (Nb_V1 and Nb_V2)
              };

मैंने इस SO प्रश्न को अनुकूलित करने की कोशिश की, लेकिन मैं इसका पता नहीं लगा सका। मैं उलझे हुए उप-अनुरोध के अंदर की Count साथ खो गया हूं।
क्या कोई मुझे समझा सकता है कि मैं कहां गलत हूं?

प्रो टिप: बोनस बिंदु यदि कोई लैम्बडा अभिव्यक्ति के साथ समकक्ष लिख सकता है


LINQ क्वेरी समझ के लिए SQL का अनुवाद करने के लिए:

  1. अलग-अलग घोषित चर के रूप में subselects का अनुवाद करें।
  2. LINQ क्लॉज ऑर्डर में प्रत्येक क्लॉज का अनुवाद करें, संपूर्ण LINQ क्वेरी पर लागू किए गए कार्यों में मोनैडिक और एग्रीगेट ऑपरेटर्स ( DISTINCT , TOP , MIN , MAX आदि) का अनुवाद करें।
  3. श्रेणी चर के रूप में तालिका उपनामों का उपयोग करें। अनाम प्रकार के फ़ील्ड नामों के रूप में स्तंभ उपनामों का उपयोग करें।
  4. कई कॉलम (जैसे समूह में) के लिए अनाम प्रकारों ( new { ... } ) का उपयोग करें।
  5. groupby एग्रीगेट रेंज वैरिएबल (जैसे MySQL के साथ) से गैर-प्रमुख मान प्राप्त करने के लिए First().field का उपयोग करें।
  6. उन परिस्थितियों को शामिल करें जो सभी समानता परीक्षणों के साथ नहीं हैं AND उन्हें शामिल होने से बाहर का उपयोग करके संभालना चाहिए, या क्रॉस उत्पाद ( from ... from ...) और फिर where । यदि आप LEFT JOIN कर रहे हैं, तो एक लैम्ब्डा जोड़ें Where क्लॉज जॉइन रेंज वैरिएबल और DefaultIfEmpty() कॉल के बीच में हो।
  7. दो तालिकाओं के बीच कई AND एड समानता परीक्षण कर रहे हैं कि JOIN स्थितियों का अनाम वस्तुओं में अनुवाद किया जाना चाहिए
  8. LEFT JOIN को योग्‍य योग्‍य से प्रयोग करके और उसके बाद joinvariable from दूसरा करने के लिए सिम्युलेटेड किया गया है ।DefaultIfEmpty .DefaultIfEmpty()
  9. सशर्त ऑपरेटर ( ?: COALESCE और एक null परीक्षण के साथ बदलें।
  10. में अनुवाद .Contains() और NOT IN ! ... निरंतर सूची के लिए शाब्दिक सरणियों या सरणी चर का उपयोग करते हुए Contains()
  11. अनुवाद करें x BETWEEN निम्न AND उच्च से निम्न <= x && x <= उच्च
  12. अनुदैर्ध्य सशर्त ऑपरेटर के लिए CASE का अनुवाद करें ?:
  13. सेलेक्ट SELECT * को चुनिंदा range_variable या joins के साथ प्रतिस्थापित किया जाना चाहिए, एक अनाम ऑब्जेक्ट जिसमें सभी रेंज वैरिएबल हों।
  14. select new { फील्ड्स को select new { ... } बदला जाना चाहिए ताकि सभी इच्छित फ़ील्ड या एक्सप्रेशन के साथ एक अनाम ऑब्जेक्ट बनाया जा सके।
  15. IIF का C # ternary सशर्त ऑपरेटर में अनुवाद करें।
  16. उचित FULL OUTER JOIN को एक एक्सटेंशन विधि के साथ संभाला जाना चाहिए।
  17. जब तक दोनों उप-प्रश्न DISTINCT होते हैं, तब तक UNION को Concat में अनुवादित करें, जिस स्थिति में आप Union अनुवाद कर सकते हैं और DISTINCT छोड़ सकते हैं।

इन नियमों को अपनी SQL क्वेरी पर लागू करना, आपको मिलता है:

var subrq = from r in Table_R
            group r by r.Id into rg
            select new { Id = rg.Key, cnt = rg.Count() };

var ansq = (from c in Table_C
            join v in Table_V on c.Id equals v.Id
            join r in subrq on c.Id equals r.Id into rj
            from r in rj.DefaultIfEmpty()
            where c.IdUser == "1234"
            group new { c, v, r } by new { c.Id, c.Title, r.cnt } into cvrg
            select new {
                cvrg.Key.Title,
                Nb_V2 = cvrg.Count(),
                Nb_V1 = cvrg.Select(cvr => cvr.v.IdUser).Distinct().Count(),
                Nb_R = (int?)cvrg.Key.cnt
            }).Distinct();

लैम्ब्डा अनुवाद मुश्किल है, लेकिन SelectMany LEFT JOIN करने के लिए LEFT JOIN का रूपांतरण ... SelectMany की जरूरत है:

var subr2 = Table_R.GroupBy(r => r.Id).Select(rg => new { Id = rg.Key, cnt = rg.Count() });
var ans2 = Table_C.Where(c => c.IdUser == "1234")
                  .Join(Table_V, c => c.Id, v => v.Id, (c, v) => new { c, v })
                  .GroupJoin(subr, cv => cv.c.Id, r => r.Id, (cv, rj) => new { cv.c, cv.v, rj })
                  .SelectMany(cvrj => cvrj.rj.DefaultIfEmpty(), (cvrj, r) => new { cvrj.c, cvrj.v, r })
                  .GroupBy(cvr => new { cvr.c.Id, cvr.c.Title, cvr.r.cnt })
                  .Select(cvrg => new { cvrg.Key.Title, Nb_V2 = cvrg.Count(), Nb_V1 = cvrg.Select(cvr => cvr.v.IdUser).Distinct().Count(), Nb_R = (int?)cvrg.Key.cnt });




sql-to-linq-conversion