Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 每个月两个日期之间的LINQ到SQL之夜_C#_Sql_Linq_Date - Fatal编程技术网

C# 每个月两个日期之间的LINQ到SQL之夜

C# 每个月两个日期之间的LINQ到SQL之夜,c#,sql,linq,date,C#,Sql,Linq,Date,在DB中,我有一个包含签入和签出日期的预订室集合,比如: ID |签入|签出 2017年1月1日至2017年1月3日 2017年1月29日至2017年2月3日 2017年2月4日至2017年2月5日 (格式为dd/MM/yyyy) 现在我想统计一下每个月有多少个晚上被预订,结果应该如下所示: ID |区域|夜间 1 | 01/2017 | 5 2 | 02/2017 | 3 var result = (from boo in context.BookingRooms

在DB中,我有一个包含签入和签出日期的预订室集合,比如:

ID |签入|签出

2017年1月1日至2017年1月3日

2017年1月29日至2017年2月3日

2017年2月4日至2017年2月5日

(格式为dd/MM/yyyy)

现在我想统计一下每个月有多少个晚上被预订,结果应该如下所示:

ID |区域|夜间

1 | 01/2017 | 5

2 | 02/2017 | 3

            var result = (from boo in context.BookingRooms
                      group boo by new { boo.CheckIn.Year, boo.CheckIn.Month } into book
                      orderby book.Key.Year descending, book.Key.Month descending
                      select new NightsPerMonth
                      {
                          Area = book.Key.Month + " / " + book.Key.Year,
                          Nights = ??

                      }).ToList();
到目前为止,这就是我所拥有的,但问题是,如果我按入住人数进行分组,那么前几个月入住的人将不在分组中,而且如果我成功分组,我不知道如何计算当前分组月份的夜数(避免计算上一个月或下一个月的夜数,即使签出或签入在本月之外),这样LINQ到SQL就不会失败


谢谢你的建议,我想你的要求对于linq查询来说是相当复杂的。 我建议两种方法来解决这个问题

方法1: 这是我的sql查询以获得所需的结果,您可以创建存储过程或函数来使用它

DECLARE @SampleData AS TABLE (Id int IDENTITY (1,1), Checkin Date, Checkout date)

INSERT INTO @SampleData VALUES ('2017-01-01', '2017-01-03'), ('2017-01-29', '2017-02-03'), ('2017-02-04', '2017-02-05')

;WITH temps AS
(
    SELECT CAST(MIN(sd.Checkin) AS Date) AS MinCheckDate, CAST(max(sd.Checkout) AS Date) as MaxCheckDate
    FROM @SampleData sd
)
-- Calculate all months from min-checkin-date to max-checkout-date.
-- By Recursive function
,allMonth AS
(
    SELECT datepart(month,t.MinCheckDate) AS [Month],
          datepart(year, t.MinCheckDate) AS [Year],
          datefromparts(datepart(year, t.MinCheckDate) , datepart(month, t.MinCheckDate) ,1) AS StartMonthDate ,
          EOMONTH(datefromparts(datepart(year, t.MinCheckDate) , datepart(month, t.MinCheckDate) ,1)) AS EndMonthDate
    FROM temps t

    UNION ALL

    SELECT  datepart(month,dateadd(month, 1, am.StartMonthDate)) AS [Month],
          datepart(year, dateadd(month, 1, am.StartMonthDate)) AS [Year],
          datefromparts(datepart(year, dateadd(month, 1, am.StartMonthDate)) , datepart(month, dateadd(month, 1, am.StartMonthDate)) ,1) AS StartMonthDate ,
          EOMONTH(datefromparts(datepart(year, dateadd(month, 1, am.StartMonthDate)) , datepart(month, dateadd(month, 1, am.StartMonthDate)) ,1)) AS EndMonthDate
    FROM allMonth am
    CROSS JOIN temps t
    WHERE dateadd(month, 1, am.StartMonthDate) <= t.MaxCheckDate
)
SELECT  CONCAT(am.[Month],'/',am.[Year]) AS Area,
       SUM(
          DATEDIFF(day,
                CAST(IIF(    am.StartMonthDate <= sd.Checkin, sd.Checkin, am.StartMonthDate) AS DATE),
                CAST(IIF(    am.EndMonthDate < sd.Checkout , dateadd(dd, 1,am.EndMonthDate), sd.Checkout)  AS date) -- if Checkout > End of month, then End of month will be calculate as a night 
          ) ) AS Nights
FROM allMonth am
LEFT JOIN @SampleData sd ON am.StartMonthDate BETWEEN sd.Checkin AND sd.Checkout OR am.EndMonthDate BETWEEN sd.Checkin AND sd.Checkout
                       OR sd.Checkin BETWEEN am.StartMonthDate AND am.EndMonthDate OR sd.Checkout BETWEEN am.StartMonthDate AND am.EndMonthDate
GROUP BY am.[Month],am.[Year]
OPTION (MAXRECURSION 0)
班级

public class BookingRooms
{
    public int Id { get; set; }
    public DateTime Checkin { get; set; }
    public DateTime Checkout { get; set; }
}

public class NightsPerMonth
{
    public string Area
    {
        get
        {
            return string.Format("{0}/{1}", Month, Year);
        }
    }
    public int Month { get; set; }

    public int Year { get; set; }

    public int Nights { get; set; }
}
和功能

public List<NightsPerMonth> GetNightsPerMonth(List<BookingRooms> lstBookRooms)
    {
        if (lstBookRooms == null || lstBookRooms.Count == 0) return null;
        var result = new List<NightsPerMonth>();
        var minCheckin = lstBookRooms.Min(x => x.Checkin);
        var maxCheckout = lstBookRooms.Max(x => x.Checkout);
        var currentMonth = minCheckin;

        while (currentMonth <= maxCheckout)
        {
            result.Add(new NightsPerMonth
            {
                Month = currentMonth.Month,
                Year = currentMonth.Year,
                Nights = GetNumberNightsOfMonth(currentMonth, lstBookRooms)
            });
            currentMonth = currentMonth.AddMonths(1);
        }

        return result;
    }

    private int GetNumberNightsOfMonth(DateTime currentMonth, List<BookingRooms> lstBookRooms)
    {
        var startDateOfMonth = new DateTime(currentMonth.Year, currentMonth.Month, 1);
        var endDateOfMonth = startDateOfMonth.AddMonths(1).AddDays(-1);

        return lstBookRooms.Where(x => IsBookRoom(startDateOfMonth, endDateOfMonth, x.Checkin, x.Checkout))
            .Sum(x => NumberNightsBookRoom(startDateOfMonth, endDateOfMonth, x.Checkin, x.Checkout));
    }

    private bool IsBookRoom(DateTime startDateOfMonth, DateTime endDateOfMonth, DateTime checkin, DateTime checkout)
    {
        if (startDateOfMonth >= checkin && startDateOfMonth <= checkout) return true;
        if (endDateOfMonth >= checkin && endDateOfMonth <= checkout) return true;

        if (checkin >= startDateOfMonth && checkin <= endDateOfMonth) return true;
        if (checkout >= startDateOfMonth && checkout <= endDateOfMonth) return true;

        return false;
    }

    private int NumberNightsBookRoom(DateTime startDateOfMonth, DateTime endDateOfMonth, DateTime checkin, DateTime checkout)
    {
        var startTimeSpan = startDateOfMonth <= checkin ? checkin : startDateOfMonth;

        // if Checkout > End of month, then End of month will be calculate as a night
        var endTimeSpan = endDateOfMonth < checkout ? endDateOfMonth.AddDays(1) : checkout;

        return (endTimeSpan - startTimeSpan).Days;
    }
公共列表GetNightsPerMonth(列出书房)
{
if(lstBookRooms==null | | lstBookRooms.Count==0)返回null;
var result=新列表();
var minCheckin=lstBookRooms.Min(x=>x.Checkin);
var maxCheckout=lstBookRooms.Max(x=>x.Checkout);
var currentMonth=minCheckin;
while(当前月份为BookRoom(每月开始日期、每月结束日期、x.签入、x.签出))
.Sum(x=>NumberNightsBookRoom(开始月底,结束月底,x.签入,x.签出));
}
private bool IsBookRoom(DateTime startDateOfMonth、DateTime endDateOfMonth、DateTime签入、DateTime签出)
{

如果(startDateOfMonth>=checkin&&startDateOfMonth=checkin&&endDateOfMonth=startDateOfMonth&&checkin=startDateOfMonth&&checkout)在您的第一个表中有ID 2出现两次?这个ID代表什么?@davidele它只是表的自动递增键-它没有任何进一步的用途,它不完全是我想要的(不是LINQ)但它解决了问题!谢谢。
public List<NightsPerMonth> GetNightsPerMonth(List<BookingRooms> lstBookRooms)
    {
        if (lstBookRooms == null || lstBookRooms.Count == 0) return null;
        var result = new List<NightsPerMonth>();
        var minCheckin = lstBookRooms.Min(x => x.Checkin);
        var maxCheckout = lstBookRooms.Max(x => x.Checkout);
        var currentMonth = minCheckin;

        while (currentMonth <= maxCheckout)
        {
            result.Add(new NightsPerMonth
            {
                Month = currentMonth.Month,
                Year = currentMonth.Year,
                Nights = GetNumberNightsOfMonth(currentMonth, lstBookRooms)
            });
            currentMonth = currentMonth.AddMonths(1);
        }

        return result;
    }

    private int GetNumberNightsOfMonth(DateTime currentMonth, List<BookingRooms> lstBookRooms)
    {
        var startDateOfMonth = new DateTime(currentMonth.Year, currentMonth.Month, 1);
        var endDateOfMonth = startDateOfMonth.AddMonths(1).AddDays(-1);

        return lstBookRooms.Where(x => IsBookRoom(startDateOfMonth, endDateOfMonth, x.Checkin, x.Checkout))
            .Sum(x => NumberNightsBookRoom(startDateOfMonth, endDateOfMonth, x.Checkin, x.Checkout));
    }

    private bool IsBookRoom(DateTime startDateOfMonth, DateTime endDateOfMonth, DateTime checkin, DateTime checkout)
    {
        if (startDateOfMonth >= checkin && startDateOfMonth <= checkout) return true;
        if (endDateOfMonth >= checkin && endDateOfMonth <= checkout) return true;

        if (checkin >= startDateOfMonth && checkin <= endDateOfMonth) return true;
        if (checkout >= startDateOfMonth && checkout <= endDateOfMonth) return true;

        return false;
    }

    private int NumberNightsBookRoom(DateTime startDateOfMonth, DateTime endDateOfMonth, DateTime checkin, DateTime checkout)
    {
        var startTimeSpan = startDateOfMonth <= checkin ? checkin : startDateOfMonth;

        // if Checkout > End of month, then End of month will be calculate as a night
        var endTimeSpan = endDateOfMonth < checkout ? endDateOfMonth.AddDays(1) : checkout;

        return (endTimeSpan - startTimeSpan).Days;
    }