[英]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.