আমি মনে করি গ্রহণযোগ্য উত্তর সহ এগুলির মধ্যে বেশিরভাগেরই সমস্যা রয়েছে কারণ তারা লিনকের সাথে আইকুয়ারেবলের ওপরে ভালভাবে কাজ করে না হয় হয় প্রচুর সার্ভারের রাউন্ড ট্রিপ করে এবং খুব বেশি ডেটা রিটার্ন করে, বা খুব বেশি ক্লায়েন্টের মৃত্যুদন্ড কার্যকর করে।
আইনিম্যারেবলের জন্য আমি শেহের উত্তর বা অনুরূপ পছন্দ করি না কারণ এর অত্যধিক মেমরির ব্যবহার রয়েছে (একটি সহজ 10000000 দুটি তালিকার লিঙ্কপ্যাড আমার 32 জিবি মেশিনে মেমরি থেকে বেরিয়েছে)।
এছাড়াও, অন্যদের বেশিরভাগই যথাযথ ফুল আউটার জয়েন বাস্তবায়িত করে না কারণ তারা ডান অ্যান্টি সেমি জয়েন্টের সাথে কনক্যাটের পরিবর্তে ডান জোড় যুক্ত ইউনিয়ন ব্যবহার করছে, যা ফলাফল থেকে ডুপ্লিকেট অভ্যন্তরীণ জোড় সারিগুলি সরিয়ে দেয় না, তবে বাম বা ডান ডেটাতে মূলত অস্তিত্ব রয়েছে এমন কোনও যথাযথ সদৃশ।
সুতরাং এখানে আমার এক্সটেনশানগুলি যা এই সমস্ত বিষয় পরিচালনা করে, এসকিউএল উত্পন্ন করার পাশাপাশি লিনকিউ-তে যোগদানকে সরাসরি এসকিউএল এ সরাসরি প্রয়োগ করে, সার্ভারে এক্সিকিউটিভ করে, এবং দ্রুত এবং স্মরণে অন্যের তুলনায় কম থাকে:
public static class Ext {
public static IEnumerable<TResult> LeftOuterJoin<TLeft, TRight, TKey, TResult>(
this IEnumerable<TLeft> leftItems,
IEnumerable<TRight> rightItems,
Func<TLeft, TKey> leftKeySelector,
Func<TRight, TKey> rightKeySelector,
Func<TLeft, TRight, TResult> resultSelector) {
return from left in leftItems
join right in rightItems on leftKeySelector(left) equals rightKeySelector(right) into temp
from right in temp.DefaultIfEmpty()
select resultSelector(left, right);
}
public static IEnumerable<TResult> RightOuterJoin<TLeft, TRight, TKey, TResult>(
this IEnumerable<TLeft> leftItems,
IEnumerable<TRight> rightItems,
Func<TLeft, TKey> leftKeySelector,
Func<TRight, TKey> rightKeySelector,
Func<TLeft, TRight, TResult> resultSelector) {
return from right in rightItems
join left in leftItems on rightKeySelector(right) equals leftKeySelector(left) into temp
from left in temp.DefaultIfEmpty()
select resultSelector(left, right);
}
public static IEnumerable<TResult> FullOuterJoinDistinct<TLeft, TRight, TKey, TResult>(
this IEnumerable<TLeft> leftItems,
IEnumerable<TRight> rightItems,
Func<TLeft, TKey> leftKeySelector,
Func<TRight, TKey> rightKeySelector,
Func<TLeft, TRight, TResult> resultSelector) {
return leftItems.LeftOuterJoin(rightItems, leftKeySelector, rightKeySelector, resultSelector).Union(leftItems.RightOuterJoin(rightItems, leftKeySelector, rightKeySelector, resultSelector));
}
public static IEnumerable<TResult> RightAntiSemiJoin<TLeft, TRight, TKey, TResult>(
this IEnumerable<TLeft> leftItems,
IEnumerable<TRight> rightItems,
Func<TLeft, TKey> leftKeySelector,
Func<TRight, TKey> rightKeySelector,
Func<TLeft, TRight, TResult> resultSelector) {
var hashLK = new HashSet<TKey>(from l in leftItems select leftKeySelector(l));
return rightItems.Where(r => !hashLK.Contains(rightKeySelector(r))).Select(r => resultSelector(default(TLeft),r));
}
public static IEnumerable<TResult> FullOuterJoin<TLeft, TRight, TKey, TResult>(
this IEnumerable<TLeft> leftItems,
IEnumerable<TRight> rightItems,
Func<TLeft, TKey> leftKeySelector,
Func<TRight, TKey> rightKeySelector,
Func<TLeft, TRight, TResult> resultSelector) where TLeft : class {
return leftItems.LeftOuterJoin(rightItems, leftKeySelector, rightKeySelector, resultSelector).Concat(leftItems.RightAntiSemiJoin(rightItems, leftKeySelector, rightKeySelector, resultSelector));
}
private static Expression<Func<TP, TC, TResult>> CastSMBody<TP, TC, TResult>(LambdaExpression ex, TP unusedP, TC unusedC, TResult unusedRes) => (Expression<Func<TP, TC, TResult>>)ex;
public static IQueryable<TResult> LeftOuterJoin<TLeft, TRight, TKey, TResult>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector,
Expression<Func<TLeft, TRight, TResult>> resultSelector) {
var sampleAnonLR = new { left = default(TLeft), rightg = default(IEnumerable<TRight>) };
var parmP = Expression.Parameter(sampleAnonLR.GetType(), "p");
var parmC = Expression.Parameter(typeof(TRight), "c");
var argLeft = Expression.PropertyOrField(parmP, "left");
var newleftrs = CastSMBody(Expression.Lambda(Expression.Invoke(resultSelector, argLeft, parmC), parmP, parmC), sampleAnonLR, default(TRight), default(TResult));
return leftItems.AsQueryable().GroupJoin(rightItems, leftKeySelector, rightKeySelector, (left, rightg) => new { left, rightg }).SelectMany(r => r.rightg.DefaultIfEmpty(), newleftrs);
}
public static IQueryable<TResult> RightOuterJoin<TLeft, TRight, TKey, TResult>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector,
Expression<Func<TLeft, TRight, TResult>> resultSelector) {
var sampleAnonLR = new { leftg = default(IEnumerable<TLeft>), right = default(TRight) };
var parmP = Expression.Parameter(sampleAnonLR.GetType(), "p");
var parmC = Expression.Parameter(typeof(TLeft), "c");
var argRight = Expression.PropertyOrField(parmP, "right");
var newrightrs = CastSMBody(Expression.Lambda(Expression.Invoke(resultSelector, parmC, argRight), parmP, parmC), sampleAnonLR, default(TLeft), default(TResult));
return rightItems.GroupJoin(leftItems, rightKeySelector, leftKeySelector, (right, leftg) => new { leftg, right }).SelectMany(l => l.leftg.DefaultIfEmpty(), newrightrs);
}
public static IQueryable<TResult> FullOuterJoinDistinct<TLeft, TRight, TKey, TResult>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector,
Expression<Func<TLeft, TRight, TResult>> resultSelector) {
return leftItems.LeftOuterJoin(rightItems, leftKeySelector, rightKeySelector, resultSelector).Union(leftItems.RightOuterJoin(rightItems, leftKeySelector, rightKeySelector, resultSelector));
}
private static Expression<Func<TP, TResult>> CastSBody<TP, TResult>(LambdaExpression ex, TP unusedP, TResult unusedRes) => (Expression<Func<TP, TResult>>)ex;
public static IQueryable<TResult> RightAntiSemiJoin<TLeft, TRight, TKey, TResult>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector,
Expression<Func<TLeft, TRight, TResult>> resultSelector) {
var sampleAnonLgR = new { leftg = default(IEnumerable<TLeft>), right = default(TRight) };
var parmLgR = Expression.Parameter(sampleAnonLgR.GetType(), "lgr");
var argLeft = Expression.Constant(default(TLeft), typeof(TLeft));
var argRight = Expression.PropertyOrField(parmLgR, "right");
var newrightrs = CastSBody(Expression.Lambda(Expression.Invoke(resultSelector, argLeft, argRight), parmLgR), sampleAnonLgR, default(TResult));
return rightItems.GroupJoin(leftItems, rightKeySelector, leftKeySelector, (right, leftg) => new { leftg, right }).Where(lgr => !lgr.leftg.Any()).Select(newrightrs);
}
public static IQueryable<TResult> FullOuterJoin<TLeft, TRight, TKey, TResult>(
this IQueryable<TLeft> leftItems,
IQueryable<TRight> rightItems,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector,
Expression<Func<TLeft, TRight, TResult>> resultSelector) {
return leftItems.LeftOuterJoin(rightItems, leftKeySelector, rightKeySelector, resultSelector).Concat(leftItems.RightAntiSemiJoin(rightItems, leftKeySelector, rightKeySelector, resultSelector));
}
}
রাইট অ্যান্টি-সেমি-জয়েনের মধ্যে পার্থক্যটি বেশিরভাগ ক্ষেত্রে লিনাক টু অবজেক্টস বা উত্সটিতে রয়েছে, তবে চূড়ান্ত উত্তরে সার্ভারে (এসকিউএল) পার্থক্য তৈরি করে একটি অপ্রয়োজনীয় অপসারণ JOIN
।
লাম্বডায় একটি Expression
মার্জ করার জন্য হ্যান্ড কোডিংটি Expression<Func<>>
লিনককিটের সাহায্যে উন্নত করা যেতে পারে তবে ভাষা / সংকলক যদি এর জন্য কিছু সহায়তা যুক্ত করে থাকে তবে এটি ভাল হবে। FullOuterJoinDistinct
এবং RightOuterJoin
ফাংশন সম্পূর্ণতার জন্য অন্তর্ভুক্ত করা হয়েছে, কিন্তু আমি পুনরায় বাস্তবায়ন হয়নিFullOuterGroupJoin
এখনো।
আমি সম্পূর্ণ বাইরের জোড়ার জন্য আরেকটি সংস্করণ লিখেছিIEnumerable
মামুলি ক্ষেত্রে অনুশীলনযোগ্য, সেখানে কমপক্ষে ছোট সংগ্রহের ক্ষেত্রে ডান অ্যান্টি আধা সেমিনের সাথে বাম বাহ্যিক জোড় সংমিশ্রণের চেয়ে প্রায় 50% দ্রুততর ক্ষেত্রে সংযুক্তির আরও । এটি একবারে বাছাইয়ের পরে প্রতিটি সংগ্রহের মধ্য দিয়ে যায়।
আমি কাস্টম সম্প্রসারণের পরিবর্তে EF এর সাথে কাজ করে এমন একটি সংস্করণের জন্য আরও একটি উত্তর যুক্ত করেছি Invoke
।