我正在尝试将SQL查询转换为LINQ。不知怎的,我的计数(distinct(x))逻辑似乎没有正常工作。原始SQL非常有效(或者我认为),但生成的SQL甚至没有返回正确的结果。
我正在尝试修复此LINQ以执行原始SQL正在执行的操作,并且以原始查询正在执行的有效方式执行。因为我被困在这里,所以这里的帮助真的很难得:(
SQL正在运行,我需要制作一个类似的LINQ:
SELECT [t1].[PersonID] AS [personid]
FROM [dbo].[Code] AS [t0]
INNER JOIN [dbo].[phonenumbers] AS [t1] ON [t1].[PhoneCode] = [t0].[Code]
INNER JOIN [dbo].[person] ON [t1].[PersonID]= [dbo].[Person].PersonID
WHERE ([t0].[codetype] = 'phone') AND (
([t0].[CodeDescription] = 'Home') AND ([t1].[PhoneNum] = '111')
OR
([t0].[CodeDescription] = 'Work') AND ([t1].[PhoneNum] = '222') )
GROUP BY [t1].[PersonID] HAVING COUNT(DISTINCT([t1].[PhoneNum]))=2
我所做的LINQ大致如下:
var ids = context.Code.Where(predicate);
var rs = from r in ids
group r by new { r.phonenumbers.person.PersonID} into g
let matchcount=g.Select(p => p.phonenumbers.PhoneNum).Distinct().Count()
where matchcount ==2
select new
{
personid = g.Key
};
不幸的是,上面的LINQ没有生成正确的结果,实际上是在内部生成到下面显示的SQL。顺便说一句,由于COUNTS,这个生成的查询也会读取所有行(约19592040)2次左右:(这也是一个很大的性能问题。请帮助/指出正确的方向。
Declare @p0 VarChar(10)='phone'
Declare @p1 VarChar(10)='Home'
Declare @p2 VarChar(10)='111'
Declare @p3 VarChar(10)='Work'
Declare @p4 VarChar(10)='222'
Declare @p5 VarChar(10)='2'
SELECT [t9].[PersonID], (
SELECT COUNT(*)
FROM (
SELECT DISTINCT [t13].[PhoneNum]
FROM [dbo].[Code] AS [t10]
INNER JOIN [dbo].[phonenumbers] AS [t11] ON [t11].[PhoneType] = [t10].[Code]
INNER JOIN [dbo].[Person] AS [t12] ON [t12].[PersonID] = [t11].[PersonID]
INNER JOIN [dbo].[phonenumbers] AS [t13] ON [t13].[PhoneType] = [t10].[Code]
WHERE ([t9].[PersonID] = [t12].[PersonID]) AND ([t10].[codetype] = @p0) AND ((([t10].[codetype] = @p1) AND ([t11].[PhoneNum] = @p2)) OR (([t10].[codetype] = @p3) AND ([t11].[PhoneNum] = @p4)))
) AS [t14]
) AS [cnt]
FROM (
SELECT [t3].[PersonID], (
SELECT COUNT(*)
FROM (
SELECT DISTINCT [t7].[PhoneNum]
FROM [dbo].[Code] AS [t4]
INNER JOIN [dbo].[phonenumbers] AS [t5] ON [t5].[PhoneType] = [t4].[Code]
INNER JOIN [dbo].[Person] AS [t6] ON [t6].[PersonID] = [t5].[PersonID]
INNER JOIN [dbo].[phonenumbers] AS [t7] ON [t7].[PhoneType] = [t4].[Code]
WHERE ([t3].[PersonID] = [t6].[PersonID]) AND ([t4].[codetype] = @p0) AND ((([t4].[codetype] = @p1) AND ([t5].[PhoneNum] = @p2)) OR (([t4].[codetype] = @p3) AND ([t5].[PhoneNum] = @p4)))
) AS [t8]
) AS [value]
FROM (
SELECT [t2].[PersonID]
FROM [dbo].[Code] AS [t0]
INNER JOIN [dbo].[phonenumbers] AS [t1] ON [t1].[PhoneType] = [t0].[Code]
INNER JOIN [dbo].[Person] AS [t2] ON [t2].[PersonID] = [t1].[PersonID]
WHERE ([t0].[codetype] = @p0) AND ((([t0].[codetype] = @p1) AND ([t1].[PhoneNum] = @p2)) OR (([t0].[codetype] = @p3) AND ([t1].[PhoneNum] = @p4)))
GROUP BY [t2].[PersonID]
) AS [t3]
) AS [t9]
WHERE [t9].[value] = @p5
谢谢!
答案 0 :(得分:0)
我认为问题可能是new { r.phonenumbers.person.PersonID}
。
为什么要在这里新建一个新对象而不是直接按r.phonenumbers.person
进行分组? new {}每次都会成为一个不同的对象,永远不会分组。
按人分组后,我会Select
group => new {person = group.person, phoneNumbers = group.person.phonenumbers}
,然后检查他们拥有多少个电话号码,然后进行最终投影。
答案 1 :(得分:0)
Drats!看起来这个错误就在我身边(GIGO原则!)
在我的ORM中,我从右到左创建了关联,而不是相反。我认为这就是问题所在。
现在只剩下问题了LINQ正在以两次方式生成一个INNER JOIN,这样可以保持最终结果的正确检索。如果我在生成的sql中发表评论,我会得到正确的结果。这是现在唯一的问题,我想我会为此提出一个新问题。谢谢你的时间!。