The idea here is to add up all the ingredients from all of the recipes. This is my query
SELECT IngredientName,sum(Amount) as Amount,Unit
FROM RecipeIngredients Join Ingredients ON RecipeIngredients.IngredientID = Ingredients.IngredientsID
GROUP BY IngredientID,IngredientName,Unit
ORDER BY IngredientName
It works great. No issues. I'm getting confused with the linq to sql syntax.
This is what I have so far.
using (lDataContext db = new lDataContext())
{
return (from ri in db.RecipeIngredients join i in db.Ingredients on ri.IngredientID equals i.IngredientsID
group new {ri,i} by new {i.IngredientsID,i.IngredientName,ri.Unit }
into table
select new {
Name = table.IngredientName
Unit = table.Unit
Amount = table.Sum(i.amount) }
).ToList();
}
Can somone please help with my syntax?
Assuming you are not using LINQ to Entities but just LINQ to SQL,
For translating SQL to LINQ,
Translate subselects as separate variables
Translate each clause in LINQ clause order, leaving monadic operators (DISTINCT, TOP, etc) as functions applied to the whole LINQ query.
Use table aliases as range variables. Use column aliases as anonymous type field names.
Use anonymous types (new { }) for multiple columns
Left Join is simulated by using a join variable and doing another from from the join variable followed by .DefaultIfEmpty().
Replace COALESCE with the conditional operator and a null test.
SELECT * must be replaced with select range variable or for joins, an anonymous object containing all the range variables.
SELECT flds must be replaced with select new { ... } creating an anonymous object with all the desired fields or expressions.
Related
This thing is driving me crazy.
I think its not that complicated but I don't get it.
I have this working SQL statement and I need the Linq statement for it.
select
a.id, a.date,
(select top 1 b.price from b where a.id = b.id and a.date >= b.date) as price
from a;
For explanation:
I have a table a with articles and a table b with a price history.
Now I need a datagrid where I can enter new entries for table a (so a view is not working) and after saving its showing me associated price
I hope I could express myself understandably
For translating SQL to LINQ query comprehension:
Translate FROM subselects as separately declared variables.
Translate each clause in LINQ clause order, leaving monadic operators (DISTINCT, TOP, etc) as functions applied to the whole LINQ query.
Use table aliases as range variables. Use column aliases as anonymous type field names.
Use anonymous types (new { }) for multiple columns
Left Join is simulated by using a into join_variable and doing another from from the join variable followed by .DefaultIfEmpty().
Replace COALESCE with the conditional operator and a null test.
SELECT * must be replaced with select range_variable or for joins, an anonymous object containing all the range variables.
SELECT fields must be replaced with select new { ... } creating an anonymous object with all the desired fields or expressions.
Proper FULL OUTER JOIN must be handled with an extension method.
For your query:
var ans = from ra in a
select new {
ra.id,
ra.date,
price = (from rb in b
where ra.id == rb.id && ra.date >= rb.date
select rb.price).First()
};
I'm not sure which syntax you're aiming for, but one of these should do the trick. I haven't tested it though.
from xa in a
select new
{
id,
date,
price = (
from xb in b
where xa.id == xb.id && xa.date >= xb.date
select xb.price
).First() // or .FirstOrDefault() if you want to allow null prices
};
or
a.Select(xa => new
{
id,
date,
price = b.First(xb => xa.id == xb.id && xa.date >= xb.date) // or .FirstOrDefault() if you want to allow null prices
});
I am trying to build a LINQ query that will accomodate a dynamic list of predicates, but also provide multiple non-equity join conditions between two tables. The ORM I am using is Telerik Open Access/Data Access going against an Oracle database.
Here is the PL-SQL Query I am trying to build in Linq.
SELECT DISTINCT
"asset".asset_number
, "hdr".revision
, "hdr".syscfg_booth_num
, "hdr".message_id
, "hdr".msg_num
, "hdr".msg_create_date
, "hdr".msg_xmit_date
, "hdr".skytel_date
FROM xfe_rep.wi_transmits "hdr"
INNER JOIN xfe_rep.pin2pagerid "asset" ON
"hdr".pin = "asset".wireless_pager_pin
AND
"hdr".msg_create_date >= "asset".effective_start_date
AND
"hdr".msg_create_date <= "asset".effective_end_date
WHERE
"hdr".field_one = ??
AND
"hdr".field_two = ??;
The WHERE clause will be added dynamically from individual predicates provided in a list. My first pass looked something like this ...
IQueryable<WITransmits> query = from wiTransmits in ctx.WITransmits
join assetMap in ctx.AssetNumberMaps
on wiTransmits.PIN equals assetMap.PIN
where
assetMap.EffectiveStartDate <= wiTransmits.MessageCreateDate &&
assetMap.EffectiveEndDate >= wiTransmits.MessageCreateDate
select wiTransmits;
foreach (Expression<Func<WITransmits, Boolean>> filter in messagePredicate)
{
query = query.Where(filter);
}
The problem with the above code is that it raises the exception "ORA-01013: user requested cancel of current operation". I believe that this is due to the number of records being returned. I have learned from other tests that when the WHERE clause is added via both the expression and method syntax to the same query it generates multiple SQL Select statements and executes each separately against the database performing the actual join in memory instead. With millions of records this is latent and impractical, I believe giving rise to the exception.
Of course when I removed the WHERE clause from the Expression syntax only one SQL statement was created, and executes as expected.
IQueryable<WITransmits> query = from wiTransmits in ctx.WITransmits
join assetMap in ctx.AssetNumberMaps
on wiTransmits.PIN equals assetMap.PIN
select wiTransmits;
foreach (Expression<Func<WITransmits, Boolean>> filter in messagePredicate)
{
query = query.Where(filter);
}
But, of course I lose the JOIN filters on the dates. The other alternative I had considered was to add multiple conditions to the JOIN. This, however, only allows me to compare for EQUALITY between two object definitons. I need to compare each property with a different comparison operator ( ==, >=, <= ) though ... so again this does not work.
IQueryable<WITransmits> query = from wiTransmits in ctx.WITransmits
join assetMap in ctx.AssetNumberMaps on
new { wiTransmits.PIN, wiTransmits.MessageCreateDate, wiTransmits.MessageCreateDate } equals
new { assetMap.PIN, assetMap.EffectiveStartDate, assetMap.EffectiveEndDate }
select wiTransmits;
foreach (Expression<Func<WITransmits, Boolean>> filter in messagePredicate)
{
query = query.Where(filter);
}
The final thought I had was to simply add the conditions as a couple of additional WHERE filters. The problem here is that the WHERE clause is between two table values and not a static value provided by the consumer. The query does not return a Queryable typed for both tables involved in the comparison so this will not work either.
IQueryable<WITransmits> query = from wiTransmits in ctx.WITransmits
join assetMap in ctx.AssetNumberMaps
on wiTransmits.PIN equals assetMap.PIN
select wiTransmits;
var joinPredicate = new List<Expression<Func<WITransmits, AssetNumberMaps, Boolean>>>();
joinPredicate.Add((wiTransmits, assetMap) => assetMap.EffectiveStartDate <= wiTransmits.MessageCreateDate);
joinPredicate.Add((wiTransmits, assetMap) => assetMap.EffectiveEndDate >= wiTransmits.MessageCreateDate);
foreach (Expression<Func<WITransmits, AssetNumberMaps, Boolean>> filter in joinPredicate)
{
query = query.Where(filter); // DOES NOT WORK
}
foreach (Expression<Func<WITransmits, Boolean>> filter in messagePredicate)
{
query = query.Where(filter);
}
Anybody have any ideas on how to do this? I am fresh out of direction ....
I have following sql query
select * from one a
inner join one b
on
(
a.weekday=b.weekday
and a.starttime =b.starttime
and a.sl>b.sl
)
where a.weekday=b.weekday and a.starttime=b.starttime and a.endtime=b.endtime
And I want it to be converted to linq statement both lambda expression and sql-like syntax. i tried but it seems like bit difficult. I have also used a tool like sqltolinq but not seem to be working.
The problem is with sql-like syntax is that my query s join has multiple elements that includes equal and greater than operator.
any help will be appreciated
LINQ only supports equijoins, but you could do an equijoin for the weekday and starttime, and endtime parts and then a where clause for the rest.
// Names changed to be more idiomatic where feasible. We have no
// idea what "sl" means.
var query = from a in db.TableA
join b in db.TableB
on new { a.WeekDay, a.StartTime, a.EndTime }
equals new { b.WeekDay, b.StartTime, b.EndTime }
where a.Sl > b.Sl
select ...;
I've looked at several other questions related to correlated subqueries but it's still not clear to me how to accomplish what I need. I'm using Entity Framework and C#, and have a table called STEWARDSHIP with the following columns:
STEWARDSHIP_ID (the primary key)
SITE_ID
VISIT_DATE
VISIT_TYPE_ID
I need to identify cases where the same combination of SITE_ID, VISIT_DATE, VISIT_TYPE_ID exists more than once because it could represent a duplicate entry made by end users in error, and then I need to report on the details of these entries. In SQL I would do this by joining to the temporary result of a GROUP BY/HAVING like so:
SELECT * FROM stewardship AS s2,
(SELECT site_id, visit_type_id, CAST(visit_date AS DATE) AS visit_date
FROM stewardship
GROUP BY site_id, visit_type_id, CAST(visit_date AS DATE)
HAVING COUNT(*) > 1) AS s
WHERE s2.site_id = s.site_id
AND s2.visit_type_id = s.visit_type_id
AND CAST(s2.visit_date AS DATE) = s.visit_date
What's the best way to accomplish this in Linq?
Since you're open to a different approach that should be more performant, here is the new SQL to get what I think you're after.
select distinct s1.*
from stewardship s1
inner join stewardship s2 on
s1.stewardship_id <> s2.stewardship_id and
s1.site_id = s2.site_id and
s1.visit_type_id = s2.visit_type_id and
cast(s1.visit_date as date) = cast(s2.visit_date as date)
order by s1.site_id, s1.visit_type_id
Now, to translate that to LINQ, you can use the following statement.
var duplicates = (
from s in Stewardships
join s2 in Stewardships
on new { s.Site_id, s.Visit_type_id, s.Visit_date.Date } equals new { s2.Site_id, s2.Visit_type_id, s2.Visit_date.Date }
where s.Stewardship_id != s2.Stewardship_id
select s)
.Distinct()
.OrderBy(s => s.Site_id)
.ThenBy(s => s.Visit_type_id)
Note that you cannot use anything other than an equijoin for expression joins, so I had to put the non-equijoin (ensuring our matches aren't on the same record via PK) in the where expression. You could also accomplish this with lambdas via the Except() extension method.
The order by is there for readability of the results and to match the SQL statement above.
I hope this helps!
It would be fairly similar to what you've already got.
from s in context.stewardships
group s by new {s.site_id, s.visit_type_id, visit_date} into g
where g.Count() > 1
select g;
This would give you groups of stewardships with similar values. You could "flatten" those results with a SelectMany afterward, but you might find them more useful to work with in groups.
Note that you may need to use SqlFunctions or something to do the equivalent of the cast to date.
Below is the SQL Query I am trying to translate
SELECT dbo.Contracts.Supplier
FROM dbo.Contracts INNER JOIN dbo.Products ON dbo.Contracts.Product = dbo.Products.Product
where dbo.Products.ProductGroup='Crude'
GROUP BY dbo.Contracts.Supplier
Am I doing something wrong because I do not get same results with the following LINQ
var result = from c in context.Contracts
join p in context.Products on c.Product equals p.Product1
where p.Product1.Equals("Crude")
group c by c.Supplier into g
select new { supplier = g.Key };
It is generating a weird statement
SELECT
1 AS [C1],
[Distinct1].[Supplier] AS [Supplier]
FROM ( SELECT DISTINCT
[Extent1].[Supplier] AS [Supplier]
FROM [dbo].[Contracts] AS [Extent1]
WHERE N'Crude' = [Extent1].[Product]
) AS [Distinct1]
Using distinct would work but to get same results, LINQ should be generating a statement like so (it's like it is ignoring the join):
SELECT distinct dbo.Contracts.Supplier
FROM dbo.Contracts INNER JOIN dbo.Products ON dbo.Contracts.Product = dbo.Products.Product
where dbo.Products.ProductGroup='Crude'
I'm assuming that you are using 'EntityFramework' or 'Linq To SQL'. If so, you should be able to use navigation properties to navigate to product and filter invalit results out. This way your query might look something like this:
var result = (from c in context.Contracts
where c.Products.Any(p => p.ProductGroup == "Crude")
select c.Supplier).Distinct();
It will automatically convert into correct query (in this case possibly without join even, just using Exists sql keyword) and return distinct suppliers. This is if I understand your objective correctly - you want to obtain all suppliers assigned to contracts that contain product from 'Crude' product group.
Basically you should try to avoid using joins from linq to sql or linq to entities as much as possible when you can use navigation properties. System will probably be better at converting them into specific sql.