簡體   English   中英

具有日期的復雜LINQ to SQL查詢

[英]Complex LINQ to SQL Query with dates

我在我的C#項目中使用LINQ to SQL構建查詢,但是我遇到了一些問題......

我想做的是選擇今天的4個持續日(例如,星期五),所以如果我們在星期五28,我想查詢:星期五21,14,7 ...最后一個四個星期五但不是今天。

這很容易,我已經完成了但是這里是復雜的部分,我想查詢我設置的例外,例如月末,即每個月的第28天到第1天,所以讓我們說我想查詢這個(十月,星期五):

今天是星期五26,我想查詢:

19日,12日,5日和9月28日(從現在開始的第四個星期五),但正如我所說的那樣,28日是月末,所以我需要在9月21日返回,這是最后一個星期五,而不是月底......我假期有同樣的問題,但我想如果我能處理月末,我可以和他們一起做...

我希望我已經解釋好了你理解我想要的東西......這是我的查詢,它正在運行,但無法處理異常。 (字段b.day是每天的ID,8表示月末,7表示假期)

var values =
    from b in dc.MyTable
    where // This means end of month
    b.day != 8

    // This triggers to query last 4 days
    && b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-28)
    || b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-21)
    || b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-14)
    || b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-7)
    orderby b.id descending
    group b.valor by b.hora_id into hg
    orderby hg.Key descending

    select new
    {
        Key = hg.Key,
        Max avg = System.Convert.ToInt32(hg.Average() + ((hg.Average() * intOkMas) / 100)),
        Min avg = System.Convert.ToInt32(hg.Average() - ((hg.Average() * intOkMenos) / 100))
    };

在嘗試查詢之前,您應該准備要檢索的日期列表:

// Get the last four days excluding today on the same weekday
var days = Enumerable.Range(1, 4).Select(i => DateTime.Today.AddDays(i * -7));

然后刪除您不想要的任何日子:

// Remove those pesky end-of-month days
days = days.Where(d => d.Day < 28 && d.Day > 1);

當您准備好要檢索的日期列表時,您才應該執行查詢:

from b in dc.MyTable
where days.Contains(b.date)  // Translated to SQL: date IN (...)
...

編輯:正如您在評論中提到的,即使您執行了任何過濾,您也需要總共四天。 因此,只需產生更多天數並采取前四個:

var days = Enumerable.Range(1, int.MaxValue - 1)
                     .Select(i => DateTime.Today.AddDays(i * -7))
                     .Where(d => d.Day < 28 && d.Day > 1)
                     .Take(4);

由於LINQ(通常是枚舉器)的工作方式,將只計算四天加上任何跳過的天數。

我強烈建議在檢索行之后編寫您的異常代碼(本月的最后一個星期五),因為這個邏輯對於LINQ語句來說似乎太復雜了。 檢索最后的4天而不是檢索最后4天。刪除每個月份的最后一個星期五。 如果您仍有5行,請刪除最后一行。

更新

var values1 =
  from b in dc.MyTable
  where // This means end of month
  b.day != 8

  // This triggers to query last 4 days
  && b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-28)
  || b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-21)
  || b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-14)
  || b.date == Convert.ToDateTime(last.ToString("dd/MM/yyy")).AddDays(-7)
  orderby b.id descending
  select b;

//Do stuff with values

var values2 = from b in values2
  group b.valor by b.hora_id into hg
  orderby hg.Key descending

  select new
  {
    Key = hg.Key,
    Max avg = System.Convert.ToInt32(hg.Average() + ((hg.Average() * intOkMas) / 100)),
    Min avg = System.Convert.ToInt32(hg.Average() - ((hg.Average() * intOkMenos) / 100))
  };

基於Allon Guralnek的回答,我會稍微修改一下:

首先,構建一個無限日期生成器:

public IEnumerable<DateTime> GetDaysLikeMe(DateTime currentDate)
{
    DateTime temp = currentDate;
    while(true)
    {
        temp = temp.AddDays(-7);
        yield return temp;
    }
}

然后,您可以通過限制為僅滿足附加條件的日期來使用延遲執行:

GetDaysLikeMe(DateTime.Now).Where(dt => /* dt meets my criteria */).Take(4)

然后你就可以使用這個生成的列表在你的LINQ to SQL中查詢,如上面建議的Allon Guralnek:

from b in dc.MyTable
where days.Contains(b.date)  // Translated to SQL: date IN (...)
...

這樣做的好處是,您可以為可接受的日期指定其他謂詞,並且仍然可以獲得至少4個日期。 只要確保對無限日期生成器進行一些邊界檢查,以防一個謂詞因任何原因總是返回false(這意味着生成器永遠不會退出)。

IE: while(temp > currentDate.AddYears(-1))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM