I want below SQL Query to be written in entity framework or LINQ.Can any one please help me on this
SQL Query:
select sum(CreditAmount)-sum(DebitAmount)
from [dbo].[JournalEntries]
where FKSubscriberID =3 and FKAccountID =1
In general, assuming C#, convert SQL to LINQ by converting phrases in LINQ comprehension syntax order, and if SQL has table aliases, use them in LINQ as range variables. Functions such as DISTINCT or TOP are called as functions over the whole query at the end. Doing multiple SUM in one query without the optimization #JonSkeet suggests requires an empty group...by to create an aggregate and then First() to reduce to a value:
(from je in dbo.JournalEntries
where je.FKSubscriberID == 3 && je.FKAccountID == 3
group je by 1 into jeg
select jeg.Sum(je => je.CreditAmount) - jeg.Sum(je => je.DebitAmount)).First()
Without the single group, you can aggregate the difference with
(from je in dbo.JournalEntries
where je.FKSubscriberID == 3 && je.FKAccountID == 3
select je.CreditAmount-je.DebitAmount).Sum()
Related
This worked in EF 6.4:
from a in Addresses
group a by new {a.StreetName, a.StreetNumber} into agrp
where agrp.Count() > 3
from aitem in agrp
select aitem
If EF Core 5 I get:
InvalidOperationException: The LINQ expression 'agrp => agrp' could
not be translated. Either rewrite the query in a form that can be
translated, or switch to client evaluation explicitly by inserting a
call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or
'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for
more information.
Why? Is there a different way to write this?
If you're OK with the data being loaded into memory, a simple solution could be to add .ToList() or .AsEnumerable() after Addresses:
from a in Addresses.ToList() // or .AsEnumerable()
group a by new {a.StreetName, a.StreetNumber} into agrp
where agrp.Count() > 3
from aitem in agrp
select aitem
Note that this (in SqlServer) translates into:
SELECT [a].[Id], [a].[StreetName], [a].[StreetNumber]
FROM [Addresses] AS [a]
In EF Core, GroupBy is (in many cases) not translated to SQL, but is run in memory.
(To avoid accidentally loading a lot of data into memory, EF will throw an exception unless .ToList() or .AsEnumerable() is called to indicate that this is intentional.)
(...) Since no database structure can represent an IGrouping, GroupBy operators have no translation in most cases. When an aggregate operator is applied to each group, which returns a scalar, it can be translated to SQL GROUP BY in relational databases. (...)
- Complex query operators, GroupBy
The article also has an example of a query which translates into group by with a filter on Count (included below).
The example doesn't fully cover the example in the question, unfortunately. It would not return the relevant Address-objects, only the group-by Key and Count.
var query = from p in context.Set<Post>()
group p by p.AuthorId into g
where g.Count() > 0
orderby g.Key
select new
{
g.Key,
Count = g.Count()
};
SELECT [p].[AuthorId] AS [Key], COUNT(*) AS [Count]
FROM [Posts] AS [p]
GROUP BY [p].[AuthorId]
HAVING COUNT(*) > 0
ORDER BY [p].[AuthorId]
This seems to work:
var addressGroupQuery = from a in Addresses
group a by new {a.StreetName, a.StreetType} into agrp
where agrp.Count() > 3
select agrp.Max(a => a.AddressID);
var addresses = from a in Addresses
where addressGroupQuery.Contains(a.AddressID)
select a;
Note the addressGroupQuery remains a deferred query (no ToList). Generates some clean looking SQL too:
SELECT [a].[AddressID], [a].[City], [a].[Country], [a].[StreetName], [a].[StreetNumber], [a].[StreetType], [a].[UnitNumber]
FROM [Address] AS [a]
WHERE EXISTS (
SELECT 1
FROM [Address] AS [a0]
GROUP BY [a0].[StreetName], [a0].[StreetType]
HAVING (COUNT(*) > 3) AND (MAX([a0].[AddressID]) = [a].[AddressID]))
I am trying to create an Entity SQL that is a union of two sub-queries.
(SELECT VALUE DISTINCT ROW(e.ColumnA, e.ColumnB, 1 AS Rank) FROM Context.Entity AS E WHERE ...)
UNION ALL
(SELECT VALUE DISTINCT ROW(e.ColumnA, e.ColumnB, 2 AS Rank) FROM Context.Entity AS E WHERE ...)
ORDER BY *??* LIMIT 50
I have tried:
ORDER BY Rank
and
ORDER BY e.Rank
but I keep getting:
System.Data.EntitySqlException: The query syntax is not valid. Near keyword 'ORDER'
Edit:
This is Entity Framework. In C#, the query is executed using:
var esql = "...";
ObjectParameter parameter0 = new ObjectParameter("p0", value1);
ObjectParameter parameter1 = new ObjectParameter("p1", value2);
ObjectQuery<DbDataRecord> query = context.CreateQuery<DbDataRecord>(esql, parameter0, parameter1);
var queryResults = query.Execute(MergeOption.NoTracking);
There is only a small portion of my application where I have to resort to using Entity SQL. Generally, the main use case is when I need to do: "WHERE Column LIKE 'A % value % with % multiple % wildcards'".
I do not think it is a problem with the Rank column. I do think it is how I am trying to apply an order by to two different esql statements joined by union all. Could someone suggest:
How to apply a ORDER BY to this kind of UNION/UNION ALL statment
How to order by the non-entity column expression.
Thanks.
I'm new to Entity Framework. I have a database query which I need to convert to Entity Framework. how to write the query in LinQ to Enity
Can someone help me on that?
SELECT
FLD1,
FLD2,
SUM(FLD3),
(TO_CHAR(FLD4,'MM/DD/YYYY'))
FROM
TABLE1
WHERE
(FLD2=XXX ) AND
(FLD3 BETWEEN TO_DATE(VARDATE,'MMDDYYYY') AND TO_DATE(VARDATE1,'MMDDYYYY'))
GROUP BY
FLD1,
FLD2,
FLD4
Well...info is sparse and you filled it with a lot of different cases something like this would do.
_context.SomeObject
.Where(x=>x.SomeField == "SomeValue" && x.SomeField > 5 && x.SomeField < 10)
.Select(x=>new { x.SomeField1, x.SomeField2, x.SomeField2, SomeField4 = x.SomeChildCollection.Sum(y=>y.SomeChildvalue)
.GroupBy(x=>new {x.SomeField1, x.SomeField2, x.SomeField3})
.ToList()
This would result in a group where the key was an object with the values SomeField1, SomeField2, SomeField3, and the object would be the an anonymous projection with the 4 properties in the Select.
In some kinds of comparisions regarding dates you might need to use EntityFunctions.
Consider the following query and notice the CALCULATE_INCENTIVE function:
SELECT EMP.* FROM EMPLOYEES EMPS
WHERE
EMP.STATUS = 1 AND
EMP.HIRE_DATE > TO_DATE('1/1/2010') AND
EMP.FIRST_NAME = 'JOHN' AND
CALCULATE_INCENTIVE(EMP.ID) > 1000
ORDER BY EMPS.ID DESC;
I was under the impression that Oracle uses the same (or similar) short-circuitry that .NET uses in its and/or logic. For example, if EMP.STATUS = 2, it won't bother evaluating the rest of the expression since the entire expression would return false anyway.
In my case, the CALCULATE_INCENTIVE function is being called on every employee in the db rather than only on the 9 records that the first three WHERE expressions return. I've even tried putting parenthesis around the specific expressions that I want to group together for short-circuit evaluation, but I can't figure it out.
Anyone have any ideas how to get the CALCULATE_INCENTIVE not to be evaluated if any of the previous expressions return false?
One way is to put the primary criteria into a subquery that Oracle can't optimize away, then put the secondary criteria into the outer query. The easiest way to ensure that Oracle doesn't optimize out the subquery is to include rownum in the select statement:
SELECT * FROM (
SELECT EMP.*, ROWNUM
FROM EMPLOYEES EMPS
WHERE
EMP.STATUS = 1
AND EMP.HIRE_DATE > TO_DATE('1/1/2010')
AND EMP.FIRST_NAME = 'JOHN')
WHERE CALCULATE_INCENTIVE(ID) > 1000
ORDER BY EMPS.ID DESC;
Oracle supports short-circuit evaluation in PL/SQL. In SQL, however, the optimizer is free to evaluate the predicates in whatever order it desires, to push predicates into views and subqueries, and to otherwise transform the SQL statement as it sees fit. This means that you should not rely on predicates being applied in a particular order and makes the order predicates appear in the WHERE clause essentially irrelevant. The indexes that are available, the optimizer statistics that are present, the optimizer parameters, and system statistics are all vastly more important than the order of predicates in the WHERE clause.
In PL/SQL, for example, you can demonstrate this with a function that throws an error if it's actually called.
SQL> ed
Wrote file afiedt.buf
1 create function throw_error( p_parameter IN NUMBER )
2 return number
3 as
4 begin
5 raise_application_error( -20001, 'The function was called' );
6 return 1;
7* end;
SQL> /
Function created.
SQL> ed
Wrote file afiedt.buf
1 declare
2 l_num NUMBER;
3 begin
4 l_num := 1;
5 if( l_num = 2 and throw_error( l_num ) = 2 )
6 then
7 null;
8 else
9 dbms_output.put_line( 'Short-circuited the AND' );
10 end if;
11 if( l_num = 1 or throw_error( l_num ) = 2 )
12 then
13 dbms_output.put_line( 'Short-circuited the OR' );
14 end if;
15* end;
16 /
Short-circuited the AND
Short-circuited the OR
PL/SQL procedure successfully completed.
In SQL, on the other hand, the order of operations is determined by the optimizer, not by you, so the optimizer is free to short-circuit or not short-circuit however it wants. Jonathan Gennick has a great article Subquery Madness! that discusses this in some detail. In your particular case, if you had a composite index on (FIRST_NAME, HIRE_DATE, STATUS) along with appropriate statistics, the optimizer would almost certainly use the index to evaluate the first three conditions and then only call the CALCULATE_INCENTIVE function for the ID's that met the other three criteria. If you created a function-based index on CALCULATE_INCENTIVE(id), the optimizer would likely use that rather than calling the function at all at runtime. But the optimizer would be perfectly free to decide to call the function for every row in either case if it decided that it would be more efficient to do so.
I have the following SQL query, which I'm struggling to convert to LINQ.
Purpose: Get the top 10 coupons from the table, ordered by the date they expire (i.e. list the ones that are about to expire first) and then randomly choosing one of those for publication.
Notes: Because of the way the database is structured, there maybe duplicate Codes in the Coupon table. Therefore, I am using a GROUP BY to enforce distinction, because I can't use DISTINCT in the sub select query (which I think is correct). The SQL query works.
SELECT TOP 1
c1.*
FROM
Coupon c1
WHERE
Code IN (
SELECT TOP 10
c2.Code
FROM
Coupon c2
WHERE
c2.Published = 0
GROUP BY
c2.Code,
c2.Expires
ORDER BY
c2.Expires
)
ORDER BY NEWID()
Update:
This is as close as I have got, but in two queries:
var result1 = (from c in Coupons
where c.Published == false
orderby c.Expires
group c by new { c.Code, c.Expires } into coupon
select coupon.FirstOrDefault()).Take(10);
var result2 = (from c in result1
orderby Guid.NewGuid()
select c).Take(1);
Here's one possible way:
from c in Coupons
from cs in
((from c in coupons
where c.published == false
select c).Distinct()
).Take(10)
where cs.ID == c.ID
select c
Keep in mind that LINQ creates a strongly-typed data set, so an IN statement has no general equivalent. I understand trying to keep the SQL tight, but LINQ may not be the best answer for this. If you are using MS SQL Server (not SQL Server Compact) you might want to consider doing this as a Stored Procedure.
Using MercurioJ's slightly buggy response, in combination with another SO suggested random row solution my solution was:
var result3 = (from c in _dataContext.Coupons
from cs in
((from c1 in _dataContext.Coupons
where
c1.IsPublished == false
select c1).Distinct()
).Take(10)
where cs.CouponId == c.CouponId
orderby _dataContext.NewId()
select c).Take(1);