我正在我的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))
};
答案 0 :(得分:3)
在尝试查询之前,您应该准备要检索的日期列表:
// 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(通常是枚举器)的工作方式,只计算四天加上任何跳过的天数。
答案 1 :(得分:2)
我强烈建议在检索行之后编写您的异常代码(本月的最后一个星期五),因为这个逻辑对于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))
};
答案 2 :(得分:2)
在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))