将 SQL 查询转换为 LINQ/点表示法
Posted
技术标签:
【中文标题】将 SQL 查询转换为 LINQ/点表示法【英文标题】:convert SQL query to LINQ / dot notation 【发布时间】:2013-07-30 11:26:40 【问题描述】:我被困在下面的 sql 到 LINQ 查询的转换中。基本上我只想将我的考试分组在我的表格成绩中,然后计算通过、失败、参加次数和通过率的总数
SELECT testID,
(SELECT COUNT(testID) FROM tblGrade AS b
WHERE b.testID= a.testID AND b.Grade < 80) AS 'Failed',
(SELECT COUNT(testID) FROM tblGrade AS b
WHERE b.testID= a.testIDAND b.Grade >= 80) AS 'Passed',
--taken = failed + passed,
--passingrate = (passed / taken) * 100
FROM dbo.tblGrade AS a
GROUP BY testID
ORDER BY testID
编辑: 我的解决方案如下:它有效,但我认为它不是最好的方法,尤其是失败和传递的属性。
var xx1 = _unitOfWork.tblGrade.GetAll().GroupBy(a => new a.testID);
var xx2 = xx1.Select(b => new
testID= b.Key.testID,
failed = _unitOfWork.tblGrade.Query(filter: a => a.testID == b.Key.testID).Where(c => c.Grade < 80).Count(),
passed = _unitOfWork.tblGrade.Query(filter: a => a.testID == b.Key.testID).Where(c => c.Grade >= 80).Count(),
//taken = failed + passed,
//passingrate = (passed / taken) * 100
).ToList();
【问题讨论】:
谢谢。我该如何使用它? 【参考方案1】:Count()
可以将谓词 (Expression<Func<T, bool>>
) 作为参数,所以我想你可以这样做
var xx2 = xx1.Select(b => new
testID= b.Key.testID,
failed = b.Count(x => x.Grade < 80),
passed = b.Count(x => x.Grade >=80),
taken = b.Count()
)
.Select(b => new
testID = b.TestID,
failed = b.failed,
passed = b.passed,
taken = b.taken,
passingrate = b.taken == 0 ? 0.0 : ((float)b.passed / b.taken) * 100
).ToList();
查询语法有(在这种情况下很有用)let
关键字,所以它可能更容易阅读
var xx2 = from b in xx1
let failed = b.Count(x => x.Grade < 80)
let passed = b.Count(x => x.Grade >= 80)
let taken = failed + passed
select new
testID = b.Key.TextID,
failed = failed,
passed = passed,
taken = taken,
passingrate = taken == 0 ? 0.0 : ((float)passed / taken) * 100
【讨论】:
很好的答案。但是sql查询中的“WHERE b.testID = a.testID”怎么样,使用“b.Count(x => x.Grade @samantha07 分组已经完成。所以你已经按 testID 分组了。计数将是“按 testID” @samantha07 顺便说一句,我不会像你那样编写“基本 SQL 查询”;) 接受为答案!非常感谢你。虽然想知道为什么通过率总是 0 为什么“b.passed / (b.failed + b.passed)”总是为零?【参考方案2】:我会这样做:
var h = list.GroupBy(a => a.testID)
.Select(a =>
int _failed = a.Count(g => g.Grade < 80);
int _passed = a.Count(g => g.Grade >= 80);
int _rate = (int)(_passed / (double)a.Count() * 100.0);
return new
testID = a.Key,
failed = _failed,
passed = _passed,
taken = a.Count(),
rate = _rate,
;
);
完整的测试代码:
void Main()
List<aGrade> list = new List<aGrade>()
new aGrade() Grade = 40, testID = 1 ,
new aGrade() Grade = 50, testID = 1 ,
new aGrade() Grade = 45, testID = 1 ,
new aGrade() Grade = 70, testID = 1 ,
new aGrade() Grade = 80, testID = 1 ,
new aGrade() Grade = 90, testID = 1 ,
new aGrade() Grade = 40, testID = 2 ,
new aGrade() Grade = 50, testID = 2 ,
new aGrade() Grade = 45, testID = 2 ,
new aGrade() Grade = 70, testID = 2 ,
new aGrade() Grade = 80, testID = 2 ,
new aGrade() Grade = 90, testID = 2 ,
new aGrade() Grade = 40, testID = 3 ,
new aGrade() Grade = 50, testID = 3 ,
new aGrade() Grade = 45, testID = 3 ,
new aGrade() Grade = 70, testID = 3 ,
new aGrade() Grade = 80, testID = 3 ,
new aGrade() Grade = 90, testID = 3 ,
;
var h = list.GroupBy(a => a.testID)
.Select(a =>
int _failed = a.Count(g => g.Grade < 80);
int _passed = a.Count(g => g.Grade >= 80);
int _rate = (int)(_passed / (double)a.Count() * 100.0);
return new
testID = a.Key,
failed = _failed,
passed = _passed,
taken = a.Count(),
rate = _rate,
;
);
h.Dump();
// Define other methods and classes here
public class aGrade
public int Grade get; set;
public int testID get; set;
NB - 此代码将像在 LinqPad 中一样工作。 (linqpad.com) 我推荐 linqpad 来测试这种类型的代码......让你的工作变得如此简单。试试看。
【讨论】:
以上是关于将 SQL 查询转换为 LINQ/点表示法的主要内容,如果未能解决你的问题,请参考以下文章