我在C#中编写了一个web api,我在get方法中有一个复杂的SQL查询。我收到了一位同事(他现在不在这里或现在可以访问)的SQL文件,其中包含:
import pandas as pd
import numpy as np
# importing dataframe
df = pd.read_csv('filename.csv', delimiter=',')
# check the dataframe
print (df)
到目前为止,这里是我所拥有的C#代码:
FROM orsrg ors WITH (NOLOCK)
INNER JOIN orkrg ork WITH (NOLOCK) ON ork.ordernr = ors.ordernr
LEFT JOIN cicmpy c1 WITH (NOLOCK) ON ork.debnr = c1.debnr
LEFT JOIN cicmpy c2 WITH (NOLOCK) ON ork.fakdebnr = c2.debnr
LEFT JOIN cicmpy c3 WITH (NOLOCK) ON ork.verzdebnr = c3.debnr
FULL JOIN humres h with (nolock) on h.res_id = ork.represent_id
正如你所看到的,我已经加入了内部和表格。 ork然后在表c1,c2,c3上做了三个左连接(尽管来自Cicmpy)。所以剩下的就是完全加入了。
我在stackoverflow上也找到了以下代码(这不是我的代码):
// This "using" is used to make the tables in the SQL query run as "WITH (NOLOCK)" ! (IsolationLevel.ReadUncommitted)
using (var txn = new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions
{
IsolationLevel = IsolationLevel.ReadUncommitted
}
))
{
// Your LINQ to SQL query goes here
var query = (from ors in _context.Orsrg
join ork in _context.Orkrg on ors.Ordernr equals ork.Ordernr
join c1 in _context.Cicmpy.DefaultIfEmpty() on ork.Debnr equals c1.Debnr
join c2 in _context.Cicmpy.DefaultIfEmpty() on ork.Fakdebnr equals c2.Debnr
join c3 in _context.Cicmpy.DefaultIfEmpty() on ork.Verzdebnr equals c3.Debnr
// FULL JOIN MUST COME HERE
);
}
该代码通过将其分成两半来完成外部连接,一旦他离开外部连接,一次右外部连接&然后将它们放在一个变量中。
我不知道如何在我原来的C#代码中执行此操作,现在它说
var firstNames = new[]
{
new { ID = 1, Name = "John" },
new { ID = 2, Name = "Sue" },
};
var lastNames = new[]
{
new { ID = 1, Name = "Doe" },
new { ID = 3, Name = "Smith" },
};
var leftOuterJoin = from first in firstNames
join last in lastNames
on first.ID equals last.ID
into temp
from last in temp.DefaultIfEmpty(new { first.ID, Name = default(string) })
select new
{
first.ID,
FirstName = first.Name,
LastName = last.Name,
};
var rightOuterJoin = from last in lastNames
join first in firstNames
on last.ID equals first.ID
into temp
from first in temp.DefaultIfEmpty(new { last.ID, Name = default(string) })
select new
{
last.ID,
FirstName = first.Name,
LastName = last.Name,
};
var fullOuterJoin = leftOuterJoin.Union(rightOuterJoin);
这些SQL查询比学校要困难得多......
答案 0 :(得分:1)
一些(有些)复杂的扩展方法将实现AsQueryable
的完全外连接并转换为SQL,尽管可能不如使用FULL OUTER JOIN
直接调用SQL那样有效。
首先是扩展程序(此处另一个答案中IEnumerable
有一些变体):
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) where TLeft : class where TRight : class where TResult : class {
var sampleAnonLR = new { left = (TLeft)null, rightg = (IEnumerable<TRight>)null };
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, (TRight)null, (TResult)null);
return leftItems.AsQueryable().GroupJoin(rightItems, leftKeySelector, rightKeySelector, (left, rightg) => new { left, rightg }).SelectMany(r => r.rightg.DefaultIfEmpty(), newleftrs);
}
private static Expression<Func<TParm, TResult>> CastSBody<TParm, TResult>(LambdaExpression ex, TParm unusedP, TResult unusedRes) => (Expression<Func<TParm, 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) where TLeft : class where TRight : class where TResult : class {
var sampleAnonLgR = new { leftg = (IEnumerable<TLeft>)null, right = (TRight)null };
var parmLgR = Expression.Parameter(sampleAnonLgR.GetType(), "lgr");
var argLeft = Expression.Constant(null, typeof(TLeft));
var argRight = Expression.PropertyOrField(parmLgR, "right");
var newrightrs = CastSBody(Expression.Lambda(Expression.Invoke(resultSelector, argLeft, argRight), parmLgR), sampleAnonLgR, (TResult)null);
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) where TLeft : class where TRight : class where TResult : class {
return leftItems.LeftOuterJoin(rightItems, leftKeySelector, rightKeySelector, resultSelector).Concat(leftItems.RightAntiSemiJoin(rightItems, leftKeySelector, rightKeySelector, resultSelector));
}
然后,您可以创建查询。我必须修改它,因为LEFT OUTER JOIN
仿真不正确。另外,我必须输入一个选择,因为它们不是完全外连接的查询理解语法,我也不想将你的查询的其余部分翻译成lambda语法。
注意:由于创建query
变量实际上并未调用数据库,因此您的事务将无法执行您所需的操作。您需要做一些事情来从事务的query
中提取结果(NOLOCK
解决)以实现对SQL的查询。
var query = (from ors in _context.Orsrg
join ork in _context.Orkrg on ors.Ordernr equals ork.Ordernr
join c1 in _context.Cicmpy on ork.Debnr equals c1.Debnr into c1j
from c1 in c1j.DefaultIfEmpty()
join c2 in _context.Cicmpy on ork.Fakdebnr equals c2.Debnr into c2j
from c2 in c2j.DefaultIfEmpty()
join c3 in _context.Cicmpy on ork.Verzdebnr equals c3.Debnr into c3j
from c3 in c3j.DefaultIfEmpty()
select new { ors, ork, c1, c2, c3 })
.FullOuterJoin(_context.Humres, left => left.ork.represent_id, h => h.res_id, (_, left, h) => new { left.ors, left.ork, left.c1, left.c2, left.c3, h });