How to display animals with all information? - laravel

I have four Tables. "Animals", "races", "animal_classes" and "animal_class_race".
Races and animal_classes are boring, only with "id" and "name".
The "animal_class_race" has: "id", "race_id", and "animal_class_id". Let us say: 1, 1, 1, and the timestamps
In "animal"-Table I have "id", "name" and "animal_class_race_id". Let us say: 1, bello, 1
What is the best way to show this animal with information from "race" and "animal_class"?

select animals.name as name, races.name as race, animal_classes.name as animal_class from animals a inner join animal_class_race acr on a.animal_class_race_id = acr.id inner join races r on r.id = acr.race_id inner join animal_classes ac on ac.id = acr.animal_class_id order by a.name

Related

How to query names from a record with multiple IDs in LINQ

I have a table [A] that has columns such as CreatedBy(ID), AuthorizedBy(ID), SentTo(ID) and I need to join them to a table [B] containing user names (UserID, FullName). How can I write a join that connects each record of table A to multiple records in table B to fill in the CreatedBy/AuthorizedBy/SentTo names using LINQ?
can give try as below , basically you have to join B with A three times
form a in A
join b in B on b.Id = a.Createdby
join b1 in B on b1.Id = a.Authrizedby
join b2 in B on b2.Id = a.SentTo
select new {
a.Id,
CreatedBy= b.FullName,
AuthorizedBy = b1.FullName,
SentTo= b2.FullName};
or
from a in A
select new {
a.ID
CreatedBy= b.FirstOrDefault(a.CreatedBy== b.Id).FullName,
AuthorizedBy = b.FirstOrDefault(a.AuthorizedBy== b.Id).FullName,
SentTo= b.FirstOrDefault(a.SentTo== b.Id).FullName
}

LINQ query with Joins and aggregate

I would request someone to please check whether my following LINQ query with 4 tables joins and group by is logically correct? Is it the correct way write LINQ query for 4 tables join and Group by clause?
My second point:
If I comment line TotalTime = tstGroup.Sum(x=>x.Duration), it works fine.
But, If I uncomment this line it say the following exception.
A first chance exception of type 'System.Data.Entity.Core.EntityCommandExecutionException' occurred in EntityFramework.SqlServer.dll
What is wrong? Please comment
Tables
Table A: Id, FirstName
Table B: Id, AId(Table A FK)
Table C: Id, BId(Table B FK), Duration
Table D: Id, AId(Table A FK). Description
tstData= (from a in _context.A
join b in _context.B on a.Id equals b.AId
join c in _context.C on b.Id equals c.BId
join d in _context.D on a.Id equals d.AId
group c by new { a= a, b= b, d= d} into tstGroup
select new myobj
{
FirstName= tstGroup.Key.a.FirstName,
Description= tstGroup.Key.d.description,
TotalTime = tstGroup.Sum(x=>x.Duration),
}).ToList();
Modified LINQ.
Do you feel it is correct now? Removed multiple group clauses.
tstData= (from a in _context.A
join b in _context.B on a.Id equals b.AId
join c in _context.C on b.Id equals c.BId
join d in _context.D on a.Id equals d.AId
group c by new { c.Id, c.Duration, d.Name, a.FirstName} into tstGroup
select new myobj
{
FirstName= tstGroup.Key.FirstName,
Description= tstGroup.Key.description,
TotalTime = tstGroup.Sum(x=>x.Duration),
}).ToList();

Left Outer Join works in LINQPad (connected using EF 4.3) but fails in application

I have an application that successfully utilizes LINQ to perform LEFT OUTER JOINs several instances; however, in one case it fails to work as expected.
Testing in LINQPad (using LINQ-to_SQL) produced the correct result; however, to be sure I changed to the LINQPad beta version 4.42.05 and successfully connected using my application's DLL and the connectionString from its web.config file (as per the Add Connection dialog). Again, LINQPad is successful in returning the proper result and clearly generates the expected left outer join in TSQL but the same code in the application fails.
In debugging the function, I get the "Object reference not set to an instance of an object." error. Please see additional descriptions after the following code and related TSQL. Note the relationship involves customer who have one-or-more stores and whoes stores have zero-or-more departments. Therefore, some returned records will not have a department (hence the requirement for the left outer join).
The following code works perfectly in LINQPad:
var model = (from h in SalesOrderHeaders
join c in Customers on h.CustomerId equals c.CustomerId
join s in Stores on h.StoreId equals s.StoreId
join d in Departments on h.DepartmentId equals d.DepartmentId into outer
from o in outer.DefaultIfEmpty()
select new
{
OrderId = h.SalesOrderHeaderId,
OrderDetailId = 1,
SalesOrderDate = h.SalesOrderDate,
DeliveryDateTime = h.DeliveryDateTime,
Customer = c.Customer,
Store = s.Store,
Department = (o.Department == null) ? "None" : o.Department,
FullDescription = "None",
Qty = 0,
UoM = "None",
}).OrderBy (m => m.OrderId);
When the code below is used in the application it fails:
var model = from h in headers
join c in customers on h.CustomerId equals c.CustomerId
join s in stores on h.StoreId equals s.StoreId
join d in departments on h.DepartmentId equals d.DepartmentId into outer
from o in outer.DefaultIfEmpty()
select new SalesOrderGridViewModel
{
OrderId = h.SalesOrderHeaderId,
OrderDetailId = 1,
SalesOrderDate = h.SalesOrderDate,
DeliveryDateTime = h.DeliveryDateTime,
Customer = c.Name,
Store = s.Name,
Department = (o.Name == null) ? "None" : o.Name,
FullDescription = "None",
Qty = 0,
UoM = "None",
};
However, when I change the code in the application so that the boolean in the assignment of the department field of the result references the join element from the headers variable (h.DepartmentId == null) as in the following code:
var model = from h in headers
join c in customers on h.CustomerId equals c.CustomerId
join s in stores on h.StoreId equals s.StoreId
join d in departments on h.DepartmentId equals d.DepartmentId into outer
from o in outer.DefaultIfEmpty()
select new SalesOrderGridViewModel
{
OrderId = h.SalesOrderHeaderId,
OrderDetailId = 1,
SalesOrderDate = h.SalesOrderDate,
DeliveryDateTime = h.DeliveryDateTime,
Customer = c.Name,
Store = s.Name,
Department = (h.DepartmentId == null) ? "None" : o.Name,
FullDescription = "None",
Qty = 0,
UoM = "None",
};
The expected result is returned.
Interestingly the subtle difference in the TSQL generated first from the original code:
SELECT [t4].[SalesOrderHeaderId] AS [OrderId], [t4].[SalesOrderDate],
[t4].[DeliveryDateTime], [t4].[Customer], [t4].[Store],
[t4].[value] AS [Department]
FROM (
SELECT [t0].[SalesOrderHeaderId], [t0].[SalesOrderDate],
[t0].[DeliveryDateTime], [t1].[Customer], [t2].[Store],
(CASE
WHEN [t3].[Department] IS NOT NULL THEN [t3].[Department]
ELSE CONVERT(NVarChar(50),#p0)
END) AS [value]
FROM [SalesOrderHeaders] AS [t0]
INNER JOIN [Customers] AS [t1] ON [t0].[CustomerId] = [t1].[CustomerId]
INNER JOIN [Stores] AS [t2] ON [t0].[StoreId] = ([t2].[StoreId])
LEFT OUTER JOIN [Departments] AS [t3]
ON [t0].[DepartmentId] = ([t3].[DepartmentId])) AS [t4]
ORDER BY [t4].[SalesOrderHeaderId]
And here from the revised code, where the boolean was changed to test the value of the DepartmentId in the original headers table ([t3].[Department] versus [t0].[DepartmentId] ), appears to be the solution:
SELECT [t4].[SalesOrderHeaderId] AS [OrderId], [t4].[SalesOrderDate],
[t4].[DeliveryDateTime], [t4].[Customer], [t4].[Store],
[t4].[value] AS [Department]
FROM (
SELECT [t0].[SalesOrderHeaderId], [t0].[SalesOrderDate],
[t0].[DeliveryDateTime], [t1].[Customer], [t2].[Store],
(CASE
WHEN [t0].[DepartmentId] IS NOT NULL THEN [t3].[Department]
ELSE CONVERT(NVarChar(50),#p0)
END) AS [value]
FROM [SalesOrderHeaders] AS [t0]
INNER JOIN [Customers] AS [t1] ON [t0].[CustomerId] = [t1].[CustomerId]
INNER JOIN [Stores] AS [t2] ON [t0].[StoreId] = ([t2].[StoreId])
LEFT OUTER JOIN [Departments] AS [t3]
ON [t0].[DepartmentId] = ([t3].[DepartmentId])) AS [t4]
ORDER BY [t4].[SalesOrderHeaderId]
While I have found a way to make this work; because it works both ways in LINQPad and successfully in numerous other LINQ queries scattered throughout my application, its failure in the original form in this one location gives me concern.
Ultimately, it appears to fail in the application when I test the returned value of the left outer join. However, this is the documented practice in many books and articles. So my final question is does anyone have any insight into why this would occur and/or how it can work in LINQPad (using the applications DLL and against the same DB)?
This is a classic example of how not to write LINQ queries - thinking in SQL and then transliterating into LINQ.
With LINQ, you can avoid the joins completely and formulate your query as follows:
from h in SalesOrderHeaders
orderby h.OrderId
select new
{
OrderId = h.SalesOrderHeaderId,
OrderDetailId = 1,
SalesOrderDate = h.SalesOrderDate,
DeliveryDateTime = h.DeliveryDateTime,
c.Customer.Customer,
s.Store.Store,
Department = (h.Department == null) ? "None" : h.Department.Department,
FullDescription = "None",
Qty = 0,
UoM = "None"
}
It appears that [t0].DepartmentID (from SalesOrderHeaders) can be null. Your LEFT OUTER JOIN relies on this value. This ends up comparing [t3].DepartmentID to null (in some cases).
You might need to use your CASE statement from the select in the JOIN as well.

Group by, Sum, Join in Linq

I have this simple sql query:
select c.LastName, Sum(b.Debit)- Sum(b.Credit) as OpenBalance from Balance as b
inner join Job as j on (b.Job = j.ID)
inner join Client as c on (j.Client = c.ID)
Group By c.LastName
and I am trying to convert it to work in linq like this:
from b in Balance
join j in Job on b.Job equals j.ID
join c in Client on j.Client equals c.ID
group b by new { c.LastName } into g
select new {
Name = c.Lastname,
OpenBalance = g.Sum(t1 => t1.Credit)
}
but when I try to run it in LINQPad I get the following message:
The name 'c' does not exist in the
current context
and it highlights c.Lastname in select new statement.
Any help on this will be greatly appreciated.
Thank you.
Well, you've grouped b by c.LastName. So after the grouping operation, you're dealing with g which is a grouping with the element type being the type of b, and the key type being the type of c.LastName. It could well be that all you need is:
select new {
Name = g.Key,
OpenBalance = g.Sum(t1 => t1.Credit)
}
... but if you need to get at any other aspects of c, you'll need to change your grouping expression.

Linq query help

I'm attempting to write a linq query which uses several tables of related data and have gotten stuck.
The expected result: I need to return the three most populous metropolitan areas per region by population descending.
tables w/sample data:
MetroAreas -- ID, Name
2, Greater New York
Cities -- ID, Name, StateID
1293912, New York City, 10
CityPopulations -- ID, CityID, CensusYear, Population
20, 1293912, 2008, 123456789
21, 1293912, 2007, 123454321
MetroAreaCities -- ID, CityID, MetroAreaID
1, 1293912, 2
States -- ID, Name, RegionID
10, New York, 5
Regions -- ID, Name
5, Northeast
I start with the metro areas. Join the MetroAreaCities to get city IDs. Join Cities to get state IDs. Join States to get the region ID. Join regions so I can filter with a where. I get stuck when I try to include CityPopulations. I only want the three most populous metro areas for a given region. Doing a simple join on the cityPopulations returns a record per year.
(Here's what I have so far, this query was written for SubSonic 3):
return from p in GeoMetroArea.All()
join q in GeoMetroAreaCity.All() on p.ID equals q.MetroAreaID
join r in GeoCity.All() on q.CityID equals r.ID
join s in GeoState.All() on r.StateID equals s.ID
join t in GeoRegion.All() on s.RegionID equals t.ID
where t.ID == regionObjectPassedToMethod.ID
select p;
Can anyone help me with this query or point me in the right direction? Thank you very very much.
I haven't compiled it, but this should get you close:
var regionID = 5;
var year = (from c in GeoCityPopulation.All()
select c.CensusYear
).Max();
var metros =
// States in Region
from s in GeoStateAll()
where s.RegionID == regionID
// Cities in State
join c in GeoCity.All() on s.CityID equals c.ID
// Metro Area for City
join mc in GeoMetroAreaCity.All() on c.ID equals mc.CityID
// Population for City
join cp in GeoCityPopulation.All() on c.ID equals cp.CityID
where cp.CensusYear = year
// Group the population values by Metro Area
group cp.Population by mc.MetroAreaID into g
select new
{
MetroID = g.Key, // Key = mc.MetroAreaID
Population = g.Sum() // g = seq. of Population values
} into mg
// Metro for MetroID
join m in GeoMetroArea.All() on mg.MetroID equals m.ID
select new { m.Name, mg.Population };

Resources