Oracle: Limiting a join with a 'many' table to just one instance? - oracle

This query returns a wide table containing horse-race results. However, one horse has multiple trainers and so this join is returning the same race-result for each trainer the horse has. How do I work around this? I've been playing around with Group By but Oracle doesn't seem to like it.
SELECT
b.meet_name AS Course,
a.race_time AS Time,
(f.jf_name||' '||f.jl_name) AS Jockey,
e.horse_name AS Horse,
c.odds,
d.place,
d.race_comment AS Note,
(g.bf_name||' '||g.bl_name) AS Breeder,
(h.tf_name||' '||h.tl_name) AS Trainer,
a.race_type AS Type,
a.distance AS Furlongs,
a.prize_money AS "Prize Money",
a.ground AS Ground
FROM proj_race_details a
JOIN proj_meet b ON a.meet_id = b.meet_id
JOIN proj_entry c ON c.race_id = a.race_id
JOIN proj_results d ON d.race_id = c.race_id AND d.horse_id = c.horse_id
JOIN proj_horses e ON e.horse_id = d.horse_id
JOIN proj_jockey f ON f.jockey_id = d.jockey_id
JOIN proj_breeder g ON g.breeder_id = e.breeder_id
JOIN proj_trainer h ON h.trainer_id = e.trainer_id;

EDIT:
This query would select only one trainer per horse. The trainer's name would be the first one, sorted alphabetically.
SELECT
b.meet_name AS Course,
a.race_time AS Time,
(f.jf_name||' '||f.jl_name) AS Jockey,
e.horse_name AS Horse,
c.odds,
d.place,
d.race_comment AS Note,
(g.bf_name||' '||g.bl_name) AS Breeder,
h.Trainer,
a.race_type AS Type,
a.distance AS Furlongs,
a.prize_money AS "Prize Money",
a.ground AS Ground
FROM proj_race_details a
JOIN proj_meet b ON a.meet_id = b.meet_id
JOIN proj_entry c ON c.race_id = a.race_id
JOIN proj_results d ON d.race_id = c.race_id AND d.horse_id = c.horse_id
JOIN proj_horses e ON e.horse_id = d.horse_id
JOIN proj_jockey f ON f.jockey_id = d.jockey_id
JOIN proj_breeder g ON g.breeder_id = e.breeder_id
JOIN
(SELECT ph.horse_id AS horse_id, MIN(pj.tf_name||' '||pj.tl_name) AS Trainer
FROM proj_trainer pj INNER JOIN proj_horses ph
ON pj.trainer_id = ph.trainer_id
GROUP BY ph.horse_id
) h
ON h.horse_id = e.horse_id;

Related

How do I outer join and group by in Entity framework Linq?

I'm having trouble getting my Linq statemnt to work when doing an outer join and a group by. Here's a SQL version of what I'm trying to accomplish:
select p.PRIMARY_KEY, min(p.EFFECTIVE_DATE), sum(IsNull(c.PAID_INDEMNITY, 0))
from PRMPOLCY p
left outer join CLMMAST c on p.PRIMARY_KEY = c.POLICY_NO
where p.UNDERWRITER_UID = 93
GROUP BY p.PRIMARY_KEY
Here's what I have in Linq (which doesn't work):
var result = from p in context.PRMPOLCies
join c in context.CLMMASTs on p.PRIMARY_KEY equals c.POLICY_NO into polClm
where (p.UNDERWRITER_UID == underwriter)
from grp in polClm.DefaultIfEmpty()
group grp by p.PRIMARY_KEY into g
select new PolicySummation()
{
PolicyNo = g.Key,
Incurred = g.Sum(grp => grp.PAID_INDEMNITY ),
EffDate = g.Min(grp => grp.PRMPOLCY.EFFECTIVE_DATE
};
Beating my head against the wall trying to figurwe this out!
Assuming you have a navigation property set up between PRMPOLCY and CLMMAST, you shouldn't need to specify the join explicitly. It's much easier to express most queries in linq without explicit joins, but rather treating your structures as a hierarchy. I don't know the specifics of your model property names, but I'd take a guess that something like this would work.
var result =
from p in context.PRMPOLCies
where (p.UNDERWRITER_UID == underwriter)
select new PolicySummation {
PolicyNo = p.PRIMARY_KEY,
Incurred = p.CLMASTs.Select(c => c.PAID_INDEMNITY).DefaultIfEmpty().Sum(),
EffDate = p.EFFECTIVE_DATE,
};
You need to include both your tables in the group clause like this:
group new { p, grp } by p.PRIMARY_KEY into g
Then in your Sum / Min
g.Sum(grp => grp.grp == null ? 0 : grp.grp.PAID_INDEMNITY )
g.Min(grp => grp.p.PRMPOLCY.EFFECTIVE_DATE)

Oracle Query don't see what's wrong

I am trying to run this Query but somehow the bottom part Label B doesn't work.
I am new to oracle and I just don't see what's wrong. Can anyone Please Help me? It would be much appreciated.
Its not returning any data when a salesperson is not tied to it. This should still return the information about the base customer regardless.
SELECT DISTINCT X.ship_sales_representative_id,
X.ship_sales_representative_name,
X.ship_sales_regional_name,
X.ship_sales_regional_head,
B.bl_customer_representative_id,
X.sp_customer_representative_id,
B.bill_customer_id,
X.ship_customer_id,
B.bill_customer_address_suffix,
X.ship_customer_address_suffix,
B.bill_customer_name,
X.ship_customer_name,
B.bill_customer_address,
X.ship_customer_address,
B.bill_customer_city,
X.ship_customer_city,
B.bill_customer_statecode,
X.ship_customer_statecode,
B.bill_customer_zipcode,
X.ship_customer_zipcode,
B.bill_customer_phonenumber,
X.ship_customer_phonenumber,
B.bill_customer_faxnumber,
X.ship_customer_faxnumber,
B.bill_customer_email,
X.ship_customer_email,
B.bill_customer_contact,
X.ship_customer_contact
FROM (SELECT DISTINCT S.rep_id Ship_Sales_Representative_ID,
S.rep_name Ship_Sales_Representative_Name,
S.reg_name Ship_Sales_Regional_Name,
S.reg_head Ship_Sales_Regional_Head,
C.rep_id Sp_Customer_Representative_ID,
C.cust_id Ship_Customer_ID,
C.addr_suffix Ship_Customer_Address_Suffix,
C.name Ship_Customer_Name,
C.addr_ln_1 Ship_Customer_Address,
C.city Ship_Customer_City,
C.state_cd Ship_Customer_StateCode,
C.zip_cd Ship_Customer_Zipcode,
C.phone_nbr Ship_Customer_PhoneNumber,
C.fax_nbr Ship_Customer_FaxNumber,
C.email Ship_Customer_Email,
C.contact Ship_Customer_Contact
FROM mdw.customer C,
mdw.sales_org S
WHERE C.rep_id = To_char(S.rep_id, 'FM000000')
AND C.cust_id = v_cust_id
AND C.addr_suffix = v_addr_suffix) X,
(SELECT DISTINCT C.rep_id Bl_Customer_Representative_ID,
C.cust_id Bill_Customer_ID,
C.addr_suffix Bill_Customer_Address_Suffix,
C.name Bill_Customer_Name,
C.addr_ln_1 Bill_Customer_Address,
C.city Bill_Customer_City,
C.state_cd Bill_Customer_StateCode,
C.zip_cd Bill_Customer_Zipcode,
C.phone_nbr Bill_Customer_PhoneNumber,
C.fax_nbr Bill_Customer_FaxNumber,
C.email Bill_Customer_Email,
C.contact Bill_Customer_Contact
FROM mdw.customer C
WHERE C.cust_id = v_cust_id
AND C.addr_suffix = '0001') B;
You probably want to add at the end of the query:
WHERE X.REP_ID = B.REP_ID
(and remove the first DISTINCT) or another condition for the JOIN otherwise this query is going to return all the combinations of records in X with records in B
Since you're looking for
AND C.CUST_ID =v_Cust_ID
you should use it in the join!
Since you're not sure that the information exists in X you should use a LEFT JOIN on X which you can do in Oracle by:
WHERE B.CUST_ID = X.CUST_ID(+)

Looking for a better way to perform Left outer join on three tables in LINQ

I am trying to do a left outer join on three tables. I know there is a way to do it in one variable but I haven't been able to figure it out. Instead I have performed two separate left outer joins and then did a left out join on those. Here is my code for that:
var outerJoin1 =
(from h in resultHours
join u in results on new {h.PhysicalUnitId, h.MonthNum} equals new {u.PhysicalUnitId, u.MonthNum} into outer
from grouping in outer.DefaultIfEmpty()
select new {timeKey = h, Key = grouping});
var outerJoin2 =
(from h in resultHours
join s in serviceHrsResults on new {h.PhysicalUnitId, h.MonthNum} equals new {s.PhysicalUnitId, s.MonthNum} into outer2
from grouping in outer2.DefaultIfEmpty()
select new {timeKey = h, Key = grouping});
var outerJoin =
(from a in outerJoin1
join b in outerJoin2 on new {a.timeKey.PlantId, a.timeKey.MonthNum} equals new {b.timeKey.PlantId, b.timeKey.MonthNum} into outer
from grouping in outer.DefaultIfEmpty()
select new{timeKey = a, Key = grouping}).Distinct();
I have tried putting the above together in one variable I can't get it to work. Here is what I have tried:
var outerjoin =
from h in resultHours
join u in results on new {h.PhysicalUnitId, h.MonthNum} equals new {u.PhysicalUnitId, u.MonthNum} into outer
from grouping in outer.DefaultIfEmpty()
from hr in resultHours
join s in serviceHrsResults on new {hr.PhysicalUnitId, hr.MonthNum} equals new {s.PhysicalUnitId, s.MonthNum} into outer2
from grouping in outer2.DefaultIfEmpty()
select new {timeKey = h && timeKey = hr, Key = grouping};
The problem with this is the two groupings conflict. i'm pretty sure I just need a single grouping right before the select but cannot figure out how to use the "grouping in" and include both outer.DefaultIfEmpty() and outer2.DefaultIfEmpty().
I would appreciate it if someone could enlighten me.
You are using duplicate range variable ids - you've got 2x grouping.
- Which grouping is it that you want in the result set ?
- What is this line expected to achieve?
timeKey = h && timeKey = hr - how do you want to combine those in the projection ?
I would try the query below, but I've changed the select part of it as your combined version doesn't make sense to me.
Let me know if it at all works for you as without data it's not easy to test this, so I can't be sure that the new version is fine.
var outerjoin =
from h in resultHours
join u in results on new {h.PhysicalUnitId, h.MonthNum} equals new {u.PhysicalUnitId, u.MonthNum} into outer
from grouping1 in outer.DefaultIfEmpty()
//from hr in resultHours
join s in serviceHrsResults on new {grouping1.PhysicalUnitId, grouping1.MonthNum} equals new {s.PhysicalUnitId, s.MonthNum} into outer2
from grouping2 in outer2.DefaultIfEmpty()
select new {timeKey = h, Key1 = grouping1, Key2 = grouping2};

Outer Join statement in LINQ

I am trying to create an outer join statement in LINQ and am not having much luck. I know that Performing an outer join requires two steps:
(1) Convert the join into a group join with into
(2) Use DefaultIfEmpty() on the group to generate the null value you expect if the joined result set is empty.
I have been using this code as an example:
var query = (from p in dc.GetTable<Person>()
join pa in dc.GetTable<PersonAddress>() on p.Id equals pa.PersonId into tempAddresses
from addresses in tempAddresses.DefaultIfEmpty()
select new { p.FirstName, p.LastName, addresses.State });
So I tried to do this:
var outerJoin =
from h in resultHours
join u in results on h.Key equals u.Key into outer
from dictionary in outer.DefaultIfEmpty()
select new {
The problem is that intellisense doesn't recognize anything in the select new {} statement. I've tried u. and h., even dictionary.
The problem I may be running into is that I'm trying to outer join two dictionaries. It doesn't seem to like that, although this is what I was told I need to do. I am obviously doing something wrong or not understanding something.
I need to join the dictionary results.Unit with the dictionary resultHours.Hours because my output is missing unitId fields under certain conditions. Doing an outer join is supposed to clear this up.
Here is the code for results:
var results =
(from v in VDimUnit
join vf in VFactEnergyAllocation on v.UnitKey equals vf.UnitKey
join vd in VDimGadsEvent on vf.GadsEventKey equals vd.GadsEventKey
join vt in VDimTime on vf.TimeKey equals vt.TimeKey
where typeCodes.Contains(vd.GadsEventTypeCode)
&& vt.YearNum >= (year - 3) && vt.YearNum <= year
group vf by new {v.PlantId, v.PhysicalUnitId, v.NetDependableCapacity, v.NetMaximumCapacity,
vt.MonthNum} into groupItem
select new {groupItem.Key.PlantId, groupItem.Key.PhysicalUnitId, groupItem.Key.NetMaximumCapacity,
groupItem.Key.MonthNum, PO_HRS = groupItem.Sum(
x=> (float)x.AllocatedEnergyMwh / groupItem.Key.NetDependableCapacity),
UO_HRS = groupItem.Sum(x=> (float)x.AllocatedEnergyMwh / groupItem.Key.NetDependableCapacity),
Unit = groupItem.Count(), groupItem.Key}).ToDictionary(x=> x.Key, x=> x);
Here is the code for resultHours:
var resultHours =
(from vt in VDimTime
join vf in VFactEnergyAllocation on vt.TimeKey equals vf.TimeKey
join vd in VDimGadsEvent on vf.GadsEventKey equals vd.GadsEventKey
join v in VDimUnit on vf.UnitKey equals v.UnitKey
group vt by new {v.PlantId, v.PhysicalUnitId, v.NetDependableCapacity, v.NetMaximumCapacity,
vt.MonthNum} into groupItem
select new {groupItem.Key.PlantId, groupItem.Key.PhysicalUnitId, groupItem.Key.NetMaximumCapacity,
Hours = groupItem.Count(), groupItem.Key}).ToDictionary(x=> x.Key.ToString(), x=> x.Hours);
This is presently how I have my output. It will change after I figure out how to do the outer join.
var finalResults =
(from r in results
orderby r.Key.MonthNum, r.Key.PlantId, r.Key.PhysicalUnitId
select new {Site = r.Key.PlantId, Unit = r.Key.PhysicalUnitId, r.Key.MonthNum, Numerator = r.Value.PO_HRS, Denominator =
resultHours[r.Key.ToString()], Weight = r.Key.NetMaximumCapacity, Data_Indicator = DATA_INDICATOR,
Budgeted = budgetedPlannedOutageHrs, Industry_Benchmark = INDUSTRY_BENCHMARK, Comments = comments,
Executive_Comments = executiveComments, Fleet_Exec_Comments = fleetExecComments});
I'm at a loss. The LINQ outer join examples I have found apaprently do not apply when joining dictionaries.

DataMapper and find_by_sql problem

Player.find_by_sql(["SELECT u.id, u.name, UNIX_TIMESTAMP(u.last_active) AS last_active, TIME_TO_SEC(TIMEDIFF(NOW(), u.last_active)) AS time_difference, r.status, SUM(d.amount) AS gold_spent, SUM(d2.amount) AS points_spent
FROM players u
LEFT JOIN guild_ranks r ON r.player_id=u.id AND r.guild_id=u.guild_id
LEFT JOIN guild_donations d ON d.player_id=u.id AND d.guild_id=u.guild_id AND d.type=1
LEFT JOIN guild_donations d2 ON d2.player_id=u.id AND d2.guild_id=u.guild_id AND d2.type=2
WHERE u.guild_id=? ORDER BY r.status, u.level DESC", guild]
How can I get the returned DataMapper::Collection to also include gold_spent and points_spent as well as time_difference?
gold_spent, points_spent, and time_difference should not be properties (or is there a way to make it so they're just DM properties and not within the database?)

Resources