views:

589

answers:

3

I have several tables that center around an organization table that simply holds a unique ID value. Each Organization can then be at a particular location and have a particular name. The tricky part is that the organizations support location and name changes with a specified effective date of each change. For this example I have 4 relevant tables:

Organization: ID (PK, int, identity)

Location: ID (PK, int, identity), Name (varchar), AltLat (float), AltLong (float)

organization_locations: organization_id(FK, int), location (FK, int), eff_date (datetime)

organization_names: organization_id (FK, int), name (ntext), eff_date (datetime), icon (nvarchar(100))

What I need to retrieve is the list of all locations along with all organizations at a given location as of a specific date and project them into my business entities. In other words, I will have a date provided and need to return for each location, the organization related to the organization_location entry with the most recent eff_date that is less than the date provided. Same thing goes for each organization, I'd need the name as of the date.

Here's what I started with but it doesn't seem to work:

Dim query = From loc In dc.Locations _
           Where loc.AltLong IsNot Nothing And loc.AltLat IsNot Nothing _
           Select New AnnexA.Entities.AnnexALocation With {.ID = loc.ID, .Name = loc.Location, .Y = loc.AltLat, .X = loc.AltLong, _
                            .Units = From ol In loc.organization_locations Let o = ol.Organization.organization_names.Where(Function(ed) (ol.eff_date < Date.Parse("1/1/2011"))).OrderByDescending(Function(od) (od.eff_date)).First() Select New AnnexA.Entities.AnnexAMillitaryUnit With {.ID = o.ID, .Name = o.name, .IconPath = o.icon}}

I'd prefer VB syntax but if you can only give me a C# query I can work with that. I've tried a few other variations but I end up getting syntax errors about an expected "}" or members not being a part of an entity set no matter what combination of parenthesis I try.

A: 

I think I understand what you're trying to do here, and it looks like some simple joins could get rid of all the complex stuff you're doing at the end of your query. (It's in C# but it should be pretty straight forward to get it to VB)

from loc in dc.Locations
join ol in dc.organization_locations on loc.ID equals ol.location
join orn in dc.organization_names on ol.organization_id equals orn.organization_id
where loc.AltLong != null
  && loc.AltLong != null
  && ol.eff_date < Date.Parse("1/1/2011")
orderby ol.eff_date
select new AnnexA.Entities.AnnexAMillitaryUnit 
    { ID = loc.ID, Name = orn.name, IconPath = orn.icon}

Let me know if this works or if it needs any fine tuning...

Noah
A: 

I need the most recent (as of a given date) location for an organization and name of an organization taken into consideration. Not just all prior to the date. For example, take the U.S. President Elect Obama. In this example there are 3 locations: his house, the Hay-Adams Hotel, and the White House. He also has gone by 3 titles in the past couple months: Senator Obama, President Elect Obama, and soon to be President Obama.

If you were to pass in the date "1/1/2008" into this query, you should get back all 3 locations, with "Senator Obama" (the organization_name) falling within his "house" (the organization_location) and the other two locations should have no "organizations" within them using our sample. If you were to pass in the date of "12/1/2008", he was still technically living at his home but he then had the title of "President Elect Obama" so the results would reflect that. If you were to pass in today's date, his name would still be "President Elect Obama" but his location changed to the "Hay-Adams Hotel". If you pass in any date after "1/20/2009", his title will be "President Obama" and his location will be "The Whitehouse".

I hope that made some sense, even if you have no interest in politics or aren't from the U.S.. I need the results to show me where everything was at and what everything was called at a given point in time.

Tom
A: 

I ended up getting this working using the following code:

Dim query4 = From loc In dc.Locations _
                 Let curNames = (From ons In dc.organization_names _
                                Where ons.eff_date <= ssDate _
                                Order By ons.eff_date Descending _
                                Group ons By ons.organization_id Into gNames = Group _
                                Select New With { _
                                    Key .Key = organization_id, _
                                    .Result = gNames.Take(1)}) _
                                    .SelectMany(Function(a) (a.Result)) _
                Let curLocs = (From oLocs In dc.organization_locations _
                               Where oLocs.eff_date <= ssDate _
                               Order By oLocs.eff_date Descending _
                               Group oLocs By oLocs.organization_id Into gLocs = Group _
                               Select New With { _
                                Key .Key = organization_id, _
                                .Result = gLocs.Take(1)}) _
                                .SelectMany(Function(a) (a.Result)) _
                Where loc.AltLat IsNot Nothing And loc.AltLong IsNot Nothing _
                Select New AnnexA.Entities.AnnexALocation With { _
                    .ID = loc.ID, .Name = loc.Location, .Y = loc.AltLat, .X = loc.AltLong, _
                    .Units = From curLoc In curLocs _
                             Where curLoc.location = loc.ID _
                             From curName In curNames _
                             Where curName.organization_id = curLoc.organization_id _
                             Select New AnnexA.Entities.AnnexAMillitaryUnit With { _
                                .ID = curLoc.organization_id, _
                                .Name = curName.name, _
                                .IconPath = curName.icon}}

Thanks for taking the time to look at this!

Tom