Как получить максимальное и минимальное время ввода / вывода для каждой даты в LINQ? - PullRequest
0 голосов
/ 29 августа 2018

Я новичок в LINQ и пытаюсь написать запрос linq, который будет эквивалентен следующему оператору SQL:

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

Я потерян в Линке:

    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(); ;

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Другим способом (в 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.

0 голосов
/ 29 августа 2018

Из запроса, который вы опубликовали, я понимаю ваши модели:

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)
                   });

Важные моменты:

  1. Свободный синтаксис гораздо более многословен, чем синтаксис запроса, но обеспечивает четкое каскадирование данных, поэтому его легче воспринимать
  2. Из запроса Sql я перевел acs_operations == "in" / "out" как условие «Где» вместо «Соединение», в идеале нам не нужно сравнивать с «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 компилируются, поэтому синтаксически правильны, вам просто нужно внести изменения в соответствии с вашим вариантом использования

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...