2013-02-27 58 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;