我是LINQ的新手,并一直在尝试编写与以下SQL语句等效的linq查询:
SELECT linking."RfidNumber",
linking."VehicleID",
acs."Date",
Min(acs."acs_datetime" ) as INTIME,
Max(acsout."acs_datetime" )
FROM dbo."acs_transaction_new" acs
INNER JOIN dbo."acs_transaction_new" acsout
ON acs."Date" = acsout."Date" AND acs."acs_operations" = 'in' AND
acsout."acs_operations" = 'out'
INNER JOIN dbo."PassLinkings" linking ON acs."acs_rfid_no" = linking."RfidNumber" AND
acs."acs_vehicle_id" = linking."VehicleID"
WHERE acsout."acs_operations" = 'out' AND acs."acs_operations" = 'in'
GROUP BY linking."RfidNumber", linking."VehicleID", acs."Date";
基本上我想要MIN acs."acs_datetime"
,其中acs."acs_operations"='in'
同样是MAX acs."acs_datetime"
,其中acs."acs_operations"='out'
表中每个日期的RfidNumber
和VehicleID
的唯一组合
我在Linq迷路了:
var query1 = (from acs in db.acs_transaction
join acsout in db.acs_transaction on acs.acs_datetime equals acsout.acs_datetime
join linking in db.PassLinkings on new { rfid = acs.acs_rfid_no, vehicleid = acs.acs_vehicle_id } equals new { rfid = linking.RfidNumber, vehicleid = (linking.VehicleID == null ? -1 : (int)linking.VehicleID) }
where acs.acs_operations == "in" && acsout.acs_operations == "out"
select new { acs.acs_rfid_no,
acs.VehicleID ,
acs."Date",
Min(acs."acs_datetime" ),// something like that
Max(acs."acs_datetime" )
}).ToList(); ;
答案 0 :(得分:1)
根据您发布的查询,以下是我对模型的理解:
public class Acs_Transaction_New_class
{
public DateTime Date {get; set;}
public string acs_operations {get; set;}
public int acs_rfid_no {get; set;}
public int acs_vehicle_id {get; set;}
public DateTime acs_datetime {get; set;}
}
public class PassLinking_Class
{
public int RfidNumber { get; set; }
public int VehicleID { get; set; }
}
// Data Placeholders to compile linq query
var result = Acs_Transaction_New
.Join(Acs_Transaction_New, acs => acs.Date, acsout => acsout.Date, (acs, acsout) => new { acs, acsout })
.Where(x => x.acs.acs_operations == "in" && x.acsout.acs_operations == "out")
.Join(PassLinkings, x => new { rfid = x.acs.acs_rfid_no, vehicleid = x.acs.acs_vehicle_id }, linking => new { rfid = linking.RfidNumber, vehicleid = linking.VehicleID}, (x, linking) => new { x.acs, x.acsout,linking })
.GroupBy(x => new { x.linking.RfidNumber, x.linking.VehicleID, x.acs.Date })
.Select(x => new
{
x.Key.RfidNumber,
x.Key.VehicleID,
x.Key.Date,
acs_min_datetime = x.Min(y => y.acs.acs_datetime),
acs_max_datetime = x.Max(y => y.acsout.acs_datetime)
});
acs_operations == "in" / "out"
转换为Where条件,而不是Join,理想情况下,我们不需要两次与“ in”和“ out”进行比较var result = from acs in Acs_Transaction_New
join acsout in Acs_Transaction_New on acs.Date equals acsout.Date
where acs.acs_operations == "in" && acsout.acs_operations == "out"
join link in PassLinkings on new { rfid = acs.acs_rfid_no, vehicleid = acs.acs_vehicle_id } equals new { rfid = link.RfidNumber, vehicleid = link.VehicleID}
group new {acs,acsout } by new { link.RfidNumber, link.VehicleID, acs.Date } into group1
select new
{
group1.Key.RfidNumber,
group1.Key.VehicleID,
group1.Key.Date,
acs_min_datetime = group1.Min(y => y.acs.acs_datetime),
acs_max_datetime = group1.Max(y => y.acsout.acs_datetime)
};
两个版本的Query都在编译中,因此从语法上讲是正确的,您只需要进行修改以适合您的用例
答案 1 :(得分:0)
另一种方法(在SQL和LINQ中)是对行进行分组,而不管输入/输出操作如何,然后在每个组内过滤和最小/最大:
var ans = from acs in dbo.acs_transaction
join linking in dbo.PassLinkings on new { RfidNumber = acs.acs_rfid_no, VehicleID = acs.acs_vehicle_id } equals new { linking.RfidNumber, linking.VehicleID }
group acs by new { linking.RfidNumber, linking.VehicleID, acs.Date } into acsg
select new {
acsg.Key.RfidNumber,
acsg.Key.VehicleID,
acsg.Key.Date,
InTime = acsg.Where(acs => acs.acs_operations == "in").Min(acs => acs.acs_datetime),
OutTime = acsg.Where(acs => acs.acs_operations == "out").Max(acs => acs.acs_datetime)
};
在使用类似的数据库查询的LINQ to SQL测试中,这生成了一个SQL查询。