SQL "IN" 语句在linq 查询错误,如何解决?
SQL "IN" statement in linq query mistake, how resolve?
我在 SQL 中有这个查询:
SELECT *
FROM TableName
WHERE myData IN (SELECT MAX(myData) AS DATA_MAX
FROM TableName
GROUP BY id1, id2)
我想在 Linq (c#) 中复制它 - 我该怎么做?
这并不是一个直接的答案,因为它不是通过 LINQ 实现的;但它确实解决了问题,并且用最少的麻烦:
您可以使用 "Dapper" 等工具来执行原始查询,而无需涉及任何 LINQ。如果您使用 LINQ-to-SQL 或 Entity Framework 之类的东西,那里的数据上下文 也 通常有一个原始查询 API你可以使用,但我要展示一个 "Dapper" 实现:
class SomeType
{
// not shown: properties that look like the columns
// of [TableName] in the database - correct names/types
}
...
var data = connection.Query<SomeType>(@"
SELECT * FROM TableName
WHERE myData IN (Select max(myData) as DATA_MAX from TableName group
by id1, id2)").AsList();
这种方法使得迁移现有 SQL 查询变得非常容易 而无需 将所有内容重写为 LINQ。
如果您使用的是 LINQ-to-SQL,DataContext
有一个类似的 ExecuteQuery<TResult>
method. Entity Framework has a SqlQuery
方法
你可以试试这个。也许它会起作用。
var myData = (from c in _context.TableName
group c by new
{
c.id1,
c.id2
} into gcs
select new
{
gcs.Max(p=>p.myData)
}).AsQueryable();
var result = (from t in _context.TableName
where myData.Contains(t.myData)
select t).ToList();
长话短说 - 不要使用 LINQ,优化查询并使用像 Dapper 这样的 microORM 将结果映射到 类:
var query = "Select * "
"from ( select *, " +
" ROW_NUMBER() OVER (partition by id1,id2 order by mydata desc) AS RN " +
" From TableName ) T " +
"where RN=1";
var data = connection.Query<SomeType>(query);
LINQ 不能替代 SQL。 ORM 一般不适合编写这样的报告查询。
报告查询需要大量优化,通常必须在生产中进行更改。您不想 每次查询更改时都必须重新部署您的应用程序。在这种情况下,far 最好创建一个视图并使用像 Dapper 这样的 microOMR 映射到它。
此特定查询可能需要 两次 table 次扫描,一次计算每个 id1,id2
的最大值,一次查找匹配 [=15] 的行=].中间数据也必须假脱机到 tempdb 中。如果 mydata
被索引覆盖,它可能不是一个如此昂贵的查询。如果不是,所有数据将被扫描两次。
另一种方法是根据id1、id2,通过mydata
计算每一行的排名。您可以使用 ROW_NUMBER、RANK、NTILE 等排名函数之一来执行此操作。
Select *
from ( select *,
ROW_NUMBER() OVER (partition by id1,id2 order by mydata desc) AS RN
From TableName) T
where RN=1
您可以直接将查询与 Dapper 一起使用,或者创建一个视图并将您的实体映射到视图,而不是 table 本身。
一种选择是创建一个 MyTableRanked
视图 :
CREATE VIEW MyTableRanked AS
select *,
ROW_NUMBER() OVER (partition by id1,id2 order by mydata desc) AS RN
From TableName
这将允许您编写:
var query="Select * from MyTableRanked where RN=@rank";
var data = connection.Query<SomeType>(query,new {rank=2});
允许您return每个 ID1、ID2 组合的前 N 条记录
我在 SQL 中有这个查询:
SELECT *
FROM TableName
WHERE myData IN (SELECT MAX(myData) AS DATA_MAX
FROM TableName
GROUP BY id1, id2)
我想在 Linq (c#) 中复制它 - 我该怎么做?
这并不是一个直接的答案,因为它不是通过 LINQ 实现的;但它确实解决了问题,并且用最少的麻烦:
您可以使用 "Dapper" 等工具来执行原始查询,而无需涉及任何 LINQ。如果您使用 LINQ-to-SQL 或 Entity Framework 之类的东西,那里的数据上下文 也 通常有一个原始查询 API你可以使用,但我要展示一个 "Dapper" 实现:
class SomeType
{
// not shown: properties that look like the columns
// of [TableName] in the database - correct names/types
}
...
var data = connection.Query<SomeType>(@"
SELECT * FROM TableName
WHERE myData IN (Select max(myData) as DATA_MAX from TableName group
by id1, id2)").AsList();
这种方法使得迁移现有 SQL 查询变得非常容易 而无需 将所有内容重写为 LINQ。
如果您使用的是 LINQ-to-SQL,DataContext
有一个类似的 ExecuteQuery<TResult>
method. Entity Framework has a SqlQuery
方法
你可以试试这个。也许它会起作用。
var myData = (from c in _context.TableName
group c by new
{
c.id1,
c.id2
} into gcs
select new
{
gcs.Max(p=>p.myData)
}).AsQueryable();
var result = (from t in _context.TableName
where myData.Contains(t.myData)
select t).ToList();
长话短说 - 不要使用 LINQ,优化查询并使用像 Dapper 这样的 microORM 将结果映射到 类:
var query = "Select * "
"from ( select *, " +
" ROW_NUMBER() OVER (partition by id1,id2 order by mydata desc) AS RN " +
" From TableName ) T " +
"where RN=1";
var data = connection.Query<SomeType>(query);
LINQ 不能替代 SQL。 ORM 一般不适合编写这样的报告查询。
报告查询需要大量优化,通常必须在生产中进行更改。您不想 每次查询更改时都必须重新部署您的应用程序。在这种情况下,far 最好创建一个视图并使用像 Dapper 这样的 microOMR 映射到它。
此特定查询可能需要 两次 table 次扫描,一次计算每个 id1,id2
的最大值,一次查找匹配 [=15] 的行=].中间数据也必须假脱机到 tempdb 中。如果 mydata
被索引覆盖,它可能不是一个如此昂贵的查询。如果不是,所有数据将被扫描两次。
另一种方法是根据id1、id2,通过mydata
计算每一行的排名。您可以使用 ROW_NUMBER、RANK、NTILE 等排名函数之一来执行此操作。
Select *
from ( select *,
ROW_NUMBER() OVER (partition by id1,id2 order by mydata desc) AS RN
From TableName) T
where RN=1
您可以直接将查询与 Dapper 一起使用,或者创建一个视图并将您的实体映射到视图,而不是 table 本身。
一种选择是创建一个 MyTableRanked
视图 :
CREATE VIEW MyTableRanked AS
select *,
ROW_NUMBER() OVER (partition by id1,id2 order by mydata desc) AS RN
From TableName
这将允许您编写:
var query="Select * from MyTableRanked where RN=@rank";
var data = connection.Query<SomeType>(query,new {rank=2});
允许您return每个 ID1、ID2 组合的前 N 条记录