[英]LINQ to SQL using GROUP BY and COUNT(DISTINCT)
I have to perform the following SQL query: 我必须执行以下SQL查询:
select answer_nbr, count(distinct user_nbr)
from tpoll_answer
where poll_nbr = 16
group by answer_nbr
The LINQ to SQL query LINQ to SQL查询
from a in tpoll_answer
where a.poll_nbr = 16 select a.answer_nbr, a.user_nbr distinct
maps to the following SQL query: 映射到以下SQL查询:
select distinct answer_nbr, distinct user_nbr
from tpoll_answer
where poll_nbr = 16
So far, so good. 到现在为止还挺好。 However the problem raises when trying to GROUP the results, as I'm not being able to find a LINQ to SQL query that maps to the first query I wrote here (thank you LINQPad for making this process a lot easier).
但是当尝试GROUP结果时问题就出现了,因为我无法找到映射到我在这里写的第一个查询的LINQ to SQL查询(感谢LINQPad让这个过程变得更容易)。 The following is the only one that I've found that gives me the desired result:
以下是我发现的唯一一个给我预期结果的:
from answer in tpoll_answer where answer.poll_nbr = 16 _
group by a_id = answer.answer_nbr into votes = count(answer.user_nbr)
Which in turns produces the follwing ugly and non-optimized at all SQL query: 这反过来会产生所有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
Any help will be more than appreciated. 任何帮助将不仅仅是赞赏。
There isn't direct support for COUNT(DISTINCT {x}))
, but you can simulate it from an IGrouping<,>
(ie what group by
returns); 没有直接支持
COUNT(DISTINCT {x}))
,但你可以从IGrouping<,>
模拟它(即返回什么group by
); I'm afraid I only "do" C#, so you'll have to translate to VB... 我担心我只会“做”C#,所以你必须翻译成VB ...
select new
{
Foo= grp.Key,
Bar= grp.Select(x => x.SomeField).Distinct().Count()
};
Here's a Northwind example: 这是一个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);
}
}
The TSQL isn't quite what we'd like, but it does the job: 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
The results, however, are correct- verifyable by running it manually: 但是,通过手动运行结果可以正确验证结果:
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);
}
With definition: 定义:
class QueryResult
{
public string Country { get; set; }
public int Count { get; set; }
}
The Northwind example cited by Marc Gravell can be rewritten with the City column selected directly by the group statement: Marc Gravell引用的Northwind示例可以使用group语句直接选择的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 has no support for Count(Distinct ...). Linq to sql不支持Count(Distinct ...)。 You therefore have to map a .NET method in code onto a Sql server function (thus Count(distinct.. )) and use that.
因此,您必须将代码中的.NET方法映射到Sql服务器函数(因此为Count(distinct ..))并使用它。
btw, it doesn't help if you post pseudo code copied from a toolkit in a format that's neither VB.NET nor C#. 顺便说一句,如果你发布从工具箱中复制的伪代码,它既不是VB.NET也不是C#的格式也无济于事。
This is how you do a distinct count query. 这是您执行非常计数查询的方式。 Note that you have to filter out the nulls.
请注意,您必须过滤掉空值。
var useranswercount = (from a in tpoll_answer
where user_nbr != null && answer_nbr != null
select user_nbr).Distinct().Count();
If you combine this with into your current grouping code, I think you'll have your solution. 如果将此与您当前的分组代码结合使用,我认为您将拥有自己的解决方案。
simple and clean example of how group by works in LINQ LINQ中group by如何工作的简单而干净的例子
http://www.a2zmenu.com/LINQ/LINQ-to-SQL-Group-By-Operator.aspx http://www.a2zmenu.com/LINQ/LINQ-to-SQL-Group-By-Operator.aspx
I wouldn't bother doing it in Linq2SQL. 我不打算在Linq2SQL中做这件事。 Create a stored Procedure for the query you want and understand and then create the object to the stored procedure in the framework or just connect direct to it.
为您想要和理解的查询创建存储过程,然后在框架中创建存储过程的对象,或者直接连接到它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.