左连接LINQ并使用Bitwise Comparisons。
我有一个可以描述的问题(感谢David B澄清这一点): 目标是从左表中返回每个OID 1行,其中左表中的记录计数等于右表中匹配行的计数。当一行中的OAG,RID和FLAG设置为FLAGS时,记录匹配。
我们正在比较的对象具有以下结构:
public class Roads : List<Road>{}
public class Road
{
public int RID;
public int OID;
public int Check = 1;
public long Flag;
}
public class Cars : List<Car> { }
public class Car
{
public int RID;
public int OID;
public long Flags;
}
对象a填充了以下数据。
Roads rs = new Roads();
Cars cs = new Cars();
Car c = new Car();
c.OID = 1;
c.RID = 1;
c.Flags = 31; // 11111
cs.Add(c);
c = new Car();
c.OID = 1;
c.RID = 2;
c.Flags = 31; //11111
cs.Add(c);
c = new Car();
c.OID = 1;
c.RID = 3;
c.Flags = 4; //00100
cs.Add(c);
Road r = new Road();
r.OID = 1;
r.RID = 1;
r.Flag = 8; //00010
rs.Add(r);
r = new Road();
r.OID = 1;
r.RID = 2;
r.Flag = 2; //01000
rs.Add(r);
r = new Road();
r.OID = 1;
r.RID = 3;
r.Flag = 4; //01000
rs.Add(r);
// r = new Road();
// r.OID = 1;
// r.RID = 3;
// r.Flag = 16; //00001
// rs.Add(r);
要查看是否设置了标志,请进行逐位比较,即cs [0] .Flags&amp;&amp; rs [0] .Flag&gt; 0为TRUE,cs [0] .Flags&amp; rs [0] .Flag = 0为FALSE
我有这个通用查询,它将获取cs中OID计数= rs中匹配OID计数的行。我现在需要一个修改过的查询,其中应用了其余的规则。我们在哪里检查Flag是否在特定行匹配的标志中。
var carLookup = cs.ToLookup(cb => c.OID);
var roadLookup = rs.ToLookup(rb => r.OID);
var results1 = from x in carLookup
let carCount = x.Count()
let roadCount = roadLookup[x.Key].Count()
where carCount == roadCount
select new { OID = x.Key, CarCount = carCount, RoadCount = roadCount };
如何扩展此功能以应用其他过滤条件?我正在努力的是在我需要它们的地方可以建立适当的过滤条件。例如,我需要比较Flags&amp;&amp;旗。但是我如何才能获得Flag和Flags以进行额外的过滤?
展开。我主要使用TSQL,所以我试图模仿我可以轻松应用于TSQL的逻辑流程。如果我用TSQL做这个,它看起来像这样(注意0的特殊情况):
SELECT cs.OID, Count(cs.OID) AS CarCount, Sum(RS.Check) AS RoadCount
FROM Cars AS cs
LEFT JOIN Roads AS RS
ON CS.oid = RS.OID
AND cs.RID = RS.RID
AND (CS.FLAGS & RS.FLAG > 0
OR (CS.FLAGS=0 AND RS.FLAG=0))
GROUP BY cs.OID
HAVING Count(cs.OID) = Sum(RS.Check)
使用该语句和上面的数据,结果将是 1,3,3。
如果我要评论最后一次添加到Roads,并取消注释下一行,将Flag更改为16,那么结果将是: 空值 如果您需要更多信息,请发表评论。
答案 0 :(得分:0)
我认为这应该等同于您的SQL语句,但是由于您的SQL使用RS.Check
但是您没有在示例代码中分配任何Check
值,因此它没有产生您提到的结果(您使用r.OID
)。我继续将r.Check = 1;
添加到每个Road
对象中,并且能够获得您提到的结果。
var query = from car in cs
from road in rs
where car.OID == road.OID
&& car.RID == road.RID
&& ((car.Flags & road.Flag) > 0 || (car.Flags == 0 && road.Flag == 0))
group new { car, road } by car.OID into grouping
let CarCount = grouping.Count()
let RoadCount = grouping.Sum(o => o.road.Check)
where CarCount == RoadCount
select new { OID = grouping.Key, CarCount, RoadCount };