2013-02-27 61 views
4

我想问我的顾客那些生日尚未到来的顾客。查询即将到来的生日

我已经试过此查询,它 - 当然 - 失败让人赞叹:

Addresses.Where(adr => adr.DateOfBirth != null && adr.DateOfBirth.Value > 
DateTime.Now).Take(15).ToList(); 

当然,这不能正常(不,如果你出生在未来)工作,我d想知道如何在没有一年的情况下查询我的Nullable<DateTime>

+6

鉴于*每个人*活着有一个即将到来的生日在某个时候,你想要多远?一个月?年底? – 2013-02-27 17:58:17

+0

'拿(15)' - 接下来的15个生日。当我在12月31日运行查询时,年底可能会出现问题 – SeToY 2013-02-27 17:59:47

+0

@Kamil在12月31日当某人在1月1日生日时,这也会失败 – SeToY 2013-02-27 18:00:47

回答

7

你能做到在同一行像这样:

context.Addresses.Where(adr => adr.DateOfBirth != null).OrderBy(adr => EntityFunctions.DiffDays(DateTime.Today, EntityFunctions.AddYears(adr.DateOfBirth, EntityFunctions.DiffYears(adr.DateOfBirth, DateTime.Today) + ((adr.DateOfBirth.Month < DateTime.Today.Month || (adr.DateOfBirth.Day <= DateTime.Today.Day && adr.DateOfBirth.Month == DateTime.Today.Month)) ? 1 : 0)))).Take(15).ToList(); 

或者更可读的格式:

var query = from adr in context.Addresses 
      where adr.DateOfBirth != null 
      let diffYears = EntityFunctions.DiffYears(adr.DateOfBirth, DateTime.Today) 
      let birthdayOccurred = adr.DateOfBirth.Month < DateTime.Today.Month || (adr.DateOfBirth.Day <= DateTime.Today.Day && adr.DateOfBirth.Month == DateTime.Today.Month) 
      let nextBirthdate = EntityFunctions.AddYears(adr.DateOfBirth, diffYears + (birthdayOccurred ? 1 : 0)) 
      let daysToBirthdate = EntityFunctions.DiffDays(DateTime.Today, nextBirthdate) 
      orderby daysToBirthdate 
      select adr; 

var result = query.Take(15).ToList(); 
+0

这个作品宏伟。谢谢,我非常感谢! :) – SeToY 2013-02-27 18:59:49

+0

@SeToY你可以尝试从我的答案中运行你的数据集的想法 - 我认为它会胜过这个答案。 – kape123 2013-02-27 19:13:11

+0

@ kape123我一定会这样做,还没有看到它。明天再试一试,然后回到你身边! – SeToY 2013-02-27 20:18:20

1

尝试类似这样; (这是工作 - 我测试过)

//A mock up value for comparison (as DayOfYear not supported in Linq) 
int doy = DateTime.Today.Month * 31 + DateTime.Today.Day; 

var results = Addresses.Where(a => a.DateOfBirth != null) 
      .OrderBy(a => 
      (a.DateOfBirth.Value.Month * 31 + a.DateOfBirth.Value.Day) + 
    (a.DateOfBirth.Value.Month * 31 + a.DateOfBirth.Value.Day > doy ? 0 : 400)) 
      .Take(15).ToList(); 
+0

这是错误的。当前日期为1月8日 - 因为7不会超过8(今天),所以不会在2月7日(这是更晚的日期)返回。 – Kamil 2013-02-27 18:12:35

+0

我认为这仍然是错误的。当日期的任何部分更大时,它将返回数据。假设我们现在有2013年2月27日。如果生日是2013-01-28怎么办?您的代码将于当天返回,因为28大于27.您必须结合月份和日期,可能是这样:'int mmdd = month * 100 + day',然后进行比较。或者可以使用类似DayOfYear的东西,但只能与年份结合使用。 – Kamil 2013-02-27 18:27:37

+1

上次编辑后,如果“今天”将在12月31日,而生日将在明年1月1日,则您的代码将无法使用。 – Kamil 2013-02-27 18:35:31

0

我不熟悉Linq,我会尝试帮助一些伪代码。

最重要的条件应该是这样的:

Date(CurrentDate.Year, DateOfBirth.Month, DateOfBirth.Day) >= CurrentDate 
|| ' OR 
Date(CurrentDate.Year + 1, DateOfBirth.Month, DateOfBirth.Day) >= CurrentDate 

这将工作12月31日了。

备选:

// consider this as pseudocode, I didnt tested that in C# 

function GetNextBirthday(DateTime DateOfBirth) 
{ 
int yearOfNextBirthday; 

int birthdayMMDD = DateOfBirth.Month*100 + DateOfBirth.Day; 
int todayMMDD = CurrentDate.Month*100 + CurrentDate.Day; 

    if (birthdayMMDD >= todayMMDD) 
    { 
     yearOfNextBirthday = CurrentDate.Year; // this year 
    } 
    else 
    { 
     yearOfNextBirthday = CurrentDate.Year + 1; // next year 
    } 

DateTime nextBirthday; 

// you have to write this line yourself, i dont remember how to make date from Y, M, D 
nextBirthday = DateFromYMD(yearOfNextBirthday, DateOfBirth.Month, DateOfBirth.Day); 

return nextBirthday; 
} 
1

我不知道你能做到这一点作为一个班轮。当然没有任何清晰度。

所需的步骤是:

  1. 创建只包含其中 月/日今天来后出生日期排序列表。
  2. 创建一个有序的列表,其中只包含当天之前的月份/日期的生日。
  3. 将第二个列表追加到第一个列表中,您现在有一个单独的列表,按 生日排序排序。
  4. 在第一个15

我认为C#代码将看起来像这样(您可能需要添加一个或两个List)。

var list1 = Addresses.Where(adr => adr.DateOfBirth != null && (adr.DateOfBirth.Value.Month > DateTime.Today.Month || (adr.DateOfBirth.Value.Month == DateTime.Today.Month && adr.DateOfBirth.Value.Day >= DateTime.Today.Day))).ToList(); 
var list2 = Addresses.Where(adr => adr.DateOfBirth != null && (adr.DateOfBirth.Value.Month < DateTime.Today.Month || (adr.DateOfBirth.Value.Month == DateTime.Today.Month && adr.DateOfBirth.Value.Day < DateTime.Today.Day))).ToList(); 
var fullList = list1.Add(list2); 
+0

您无法创建今天之前和之后的生日清单。第一个原因:12月31日你的更高日期列表将为空。当某人1月1日有生日 - 他将成为下一个有生日的人,但你不会看到这个。 – Kamil 2013-02-27 18:40:20

+0

我假设他的名单是已经出生的人(否则他们不能成为客户)。第一个列表是今天或以后生日的人。第二个列表是生日已经过去的人。通过这样结合他们,我创建了明年的生日值。 – ThatBlairGuy 2013-02-27 18:43:17

0

这里是我的“一个班轮”条目:

DateTime now = DateTime.Now; 
var next15 = 
    from a in db.Addresses 
    where a.DateOfBirth != null 
    let diff = EntityFunctions.DiffSeconds(
     EntityFunctions.AddYears(now, -EntityFunctions.DiffYears(a.DateOfBirth, now)), 
     a.DateOfBirth) 
    orderby diff >= 0 ? diff : diff + 366*24*60*60 
    select new a; 

var res = next15.Take(15).ToList(); 

刚刚与SQL数据库测试 - 和它的作品般的魅力;)

0

这是同样的解决方案@Aducci但可空日期和DBFunctions,因为EntityFunctions已被弃用。

  pacientes = from paciente in pacientes 
       where paciente.Nascimento != null 
       let diffYears = DbFunctions.DiffYears(paciente.Nascimento, DateTime.Today) 
       let birthdayOccurred = paciente.Nascimento.Value.Month < DateTime.Today.Month 
       || (paciente.Nascimento.Value.Day <= DateTime.Today.Day && paciente.Nascimento.Value.Month == DateTime.Today.Month) 
       let nextBirthdate = DbFunctions.AddYears(paciente.Nascimento, diffYears + (birthdayOccurred ? 1 : 0)) 
       let daysToBirthdate = DbFunctions.DiffDays(DateTime.Today, nextBirthdate) 
       orderby daysToBirthdate 
       select paciente;