LINQ to SQL使用GROUP BY和COUNT(DISTINCT)
我必须执行下面的SQL查询:
select answer_nbr, count(distinct user_nbr) from tpoll_answer where poll_nbr = 16 group by answer_nbr
LINQ to SQL查询
from a in tpoll_answer where a.poll_nbr = 16 select a.answer_nbr, a.user_nbr distinct
映射到以下SQL查询:
select distinct answer_nbr, distinct user_nbr from tpoll_answer where poll_nbr = 16
到现在为止还挺好。 然而,当试图对结果进行分组时,问题会引发,因为我无法find映射到这里写的第一个查询的LINQ to SQL查询(感谢LINQPad让这个过程变得更容易)。 以下是唯一一个我发现给我想要的结果:
from answer in tpoll_answer where answer.poll_nbr = 16 _ group by a_id = answer.answer_nbr into votes = count(answer.user_nbr)
在所有的SQL查询中,反过来又会产生丑陋的和非优化的:
SELECT [t1].[answer_nbr] AS [a_id], ( SELECT COUNT(*) FROM ( SELECT CONVERT(Bit,[t2].[user_nbr]) AS [value], [t2].[answer_nbr], [t2].[poll_nbr] FROM [TPOLL_ANSWER] AS [t2] ) AS [t3] WHERE ([t3].[value] = 1) AND ([t1].[answer_nbr] = [t3].[answer_nbr]) AND ([t3].[poll_nbr] = @p0) ) AS [votes] FROM ( SELECT [t0].[answer_nbr] FROM [TPOLL_ANSWER] AS [t0] WHERE [t0].[poll_nbr] = @p0 GROUP BY [t0].[answer_nbr] ) AS [t1] -- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [16] -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.1
任何帮助将不胜感激。
COUNT(DISTINCT {x}))
没有直接的支持COUNT(DISTINCT {x}))
,但是你可以从一个IGrouping<,>
(也就是返回group by
)来模拟它。 恐怕我只“做”C#,所以你必须翻译成VB …
select new { Foo= grp.Key, Bar= grp.Select(x => x.SomeField).Distinct().Count() };
这是Northwind的一个例子:
using(var ctx = new DataClasses1DataContext()) { ctx.Log = Console.Out; // log TSQL to console var qry = from cust in ctx.Customers where cust.CustomerID != "" group cust by cust.Country into grp select new { Country = grp.Key, Count = grp.Select(x => x.City).Distinct().Count() }; foreach(var row in qry.OrderBy(x=>x.Country)) { Console.WriteLine("{0}: {1}", row.Country, row.Count); } }
TSQL并不是我们想要的,但是它完成了这个工作:
SELECT [t1].[Country], ( SELECT COUNT(*) FROM ( SELECT DISTINCT [t2].[City] FROM [dbo].[Customers] AS [t2] WHERE ((([t1].[Country] IS NULL) AND ([t2].[Country] IS NULL)) OR (([t1] .[Country] IS NOT NULL) AND ([t2].[Country] IS NOT NULL) AND ([t1].[Country] = [ t2].[Country]))) AND ([t2].[CustomerID] <> @p0) ) AS [t3] ) AS [Count] FROM ( SELECT [t0].[Country] FROM [dbo].[Customers] AS [t0] WHERE [t0].[CustomerID] <> @p0 GROUP BY [t0].[Country] ) AS [t1] -- @p0: Input NVarChar (Size = 0; Prec = 0; Scale = 0) [] -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.1
但是,结果是正确的 – 可以通过手动运行来validation结果:
const string sql = @" SELECT c.Country, COUNT(DISTINCT c.City) AS [Count] FROM Customers c WHERE c.CustomerID != '' GROUP BY c.Country ORDER BY c.Country"; var qry2 = ctx.ExecuteQuery<QueryResult>(sql); foreach(var row in qry2) { Console.WriteLine("{0}: {1}", row.Country, row.Count); }
定义如下:
class QueryResult { public string Country { get; set; } public int Count { get; set; } }
Marc Gravell引用的Northwind例子可以用集团声明直接select的City列重写:
from cust in ctx.Customers where cust.CustomerID != "" group cust.City /*here*/ by cust.Country into grp select new { Country = grp.Key, Count = grp.Distinct().Count() };
Linq to sql不支持Count(Distinct …)。 因此,您必须将代码中的.NET方法映射到Sql服务器函数(因此Count(distinct ..))并使用它。
顺便说一句,它不会帮助,如果你发布从工具包复制的既不是VB.NET也不是C#的格式的伪代码。
这是你如何做一个不同的计数查询。 请注意,您必须过滤出空值。
var useranswercount = (from a in tpoll_answer where user_nbr != null && answer_nbr != null select user_nbr).Distinct().Count();
如果你把这个结合到你当前的分组代码中,我想你会有你的解决scheme。
如何在LINQ中工作的简单和干净的例子
http://www.a2zmenu.com/LINQ/LINQ-to-SQL-Group-By-Operator.aspx
我不会在Linq2SQL中做这件事。 为你想要查询的查询创build一个存储过程,然后创build对象到框架中的存储过程,或直接连接到它。