I recently purchased LINQPad in hopes that it would allow me to convert SQL statements into LINQ statements.
Using LINQPad, I am able to attach a DB and run the SQL statement which returns the results I need.
But I can not find a 'command' to convert that SQL statement into LINQ.
Can you please let me know how to convert SQL to LINQ by using LINQPad OR another tool?
There is a tool called Linqer, but be careful: transliterating from SQL to LINQ can give you the worst of both worlds.
For instance, suppose you want all purchases of $1000 or greater paid for in cash or by customers who live in Washington. Here's the query in SQL:
SELECT p.*
FROM Purchase p
LEFT OUTER JOIN
Customer c INNER JOIN Address a ON c.AddressID = a.ID
ON p.CustomerID = c.ID
WHERE
(a.State = 'WA' || p.CustomerID IS NULL)
AND p.ID in
(
SELECT PurchaseID FROM PurchaseItem
GROUP BY PurchaseID HAVING SUM (SaleAmount) > 1000
)
How would translate this to LINQ? The wrong way is to transliterate the query into LINQ, trying to reproduce the outer and inner joins, subquery and group clause. The right way is to map your original query (in English) directly into LINQ, leveraging LINQ's linear flow of data and association properties:
I want all purchases...
from p in db.Purchases
...of $1000 or greater...
where p.PurchaseItems.Sum (pi => pi.SaleAmount) > 1000
...paid for in cash...
where p.Customer == null
...or by customers who live in Washington
|| p.Customer.Address.State == "WA"
Here's the final query:
from p in db.Purchases
where p.PurchaseItems.Sum (pi => pi.SaleAmount) > 1000
where p.Customer == null || p.Customer.Address.State == "WA"
select p
More info here.
In general there are no tools to covert SQL to Linq as #andres-abel mention before, but sometimes you have to write Linq that will execute exactly as specified SQL (for example because of performance issues, backward compatability or some other reasons).
In this case I'll advice you to do reverse engineering by yourself:
configure logging of dump SQL statements generated by Linq to stdout using
ObjectQuery.ToTraceString,
DbCommand.CommandText,
logger availabe to your data source
manually rewrite Linq statement until you'll get what you need
LinqPad contains no SQL->LINQ translator. LinqPad does actually not contain any LINQ->SQL translator either. It relies on the .Net Linq-to-Sql library or Entity framework for the translation.
I don't know of any other tool with that capability either. In simple cases it would be possible to make one, but for more complex scenarios it would be impossible as there is no LINQ expression that matches some SQL constructs.
Related
I am looking to convert the below Legacy SQL Query to Standard SQL. The issue I am having is that I need to unnest two tables (labels and credits). How can I convert this query? Thanks!
I run into a "Scalar subquery produced more than one element" whenever I try to rewrite this query (see below).
Legacy SQL Query I am trying to rewrite:
SELECT
service.description,
sku.description,
usage_start_time,
usage_end_time,
labels.key,
labels.value,
cost,
usage.amount,
project.name,
credits.name,
credits.amount
FROM
flatten([gcp_billing_data.gcp_billing_export],
credits)
What I have tried so far in Standard SQL:
SELECT
service.description AS service,
sku.description AS sku,
usage_start_time,
usage_end_time,
l.key,
l.value,
cost,
usage.amount AS usage,
project.name AS project,
c.name AS credit,
c.amount
FROM
`gcp_billing_data.gcp_billing_export`,
UNNEST(labels) AS l,
UNNEST(credits) AS c
Group by 1,2,3,4,5,7,8,9,10,11
This query runs, but the number of rows is significantly less than I would expect.
quick and formal fix for your query in Standard SQL is something like to replace below
(select l.value from unnest(labels) as l)
with
(select string_agg(l.value) from unnest(labels) as l)
But it is still not exactly the same as what initial version of your Legacy SQL version of query is doing
I have a query working the way I want, by executing SQL directly, but am curious (just for my own learning purposes) if this same thing could be done in an ActiveRecord statement?
The part I'm struggling with the most is the COALESCE part of this query, which just makes sure that any NULL values from the LEFT JOIN are counted as zeros instead, to keep the summation in order.
Any ideas? I'm using Postgres.
SELECT Inventories.id, Inventories.name, Inventories.unit_of_measure,
COALESCE(Sum(Stocks.count),0) as totalcount
FROM Inventories
LEFT JOIN Stocks
ON Inventories.id = Stocks.inventory_id
WHERE Inventories.property = 'material' AND Inventories.organization_id = #{current_organization.id}
GROUP BY Inventories.id, Stocks.inventory_id
ORDER BY totalcount ASC
LIMIT(5)")
This is the closest I've gotten for an AR equivalent. When I try to add a sum or something like it, that's when it errors out.
#lowmaterials = current_organization.inventories.materials.left_joins(:stocks).group(:id, :inventory_id).order(count: :asc).limit(5)
You can use ActiveRecord::QueryMethods#select:
your_relation.select("column1, column2, COALESCE(1,2) AS column3").left_joins...
I have this query to get results out of my database. My problem is that the selectedanswer part of the select statement does not pull all of the data from r.textboxmulti.
Below is my query.
<cfquery name="fullResults" datasource="#variables.dsn#">
select s.id, s.name surveyname, q.question, subq.answer subquestion, isnull(isnull(isnull(isnull(a.answer, **r.textboxmulti**),r.other),r.textbox),r.truefalse) as **selectedanswer**, a.*, r.*
from results r
join questions q on r.questionidfk = q.id
left join answers subq on r.itemidfk = subq.id
left join answers a on r.answeridfk = a.id
join surveys s on q.surveyidfk = s.id
where owneridfk = <cfqueryparam value="#arguments.ownerid#" cfsqltype="CF_SQL_VARCHAR" maxlength="35">
order by s.id, owneridfk, q.rank, subq.rank desc
</cfquery
Try using COALESCE instead of ISNULL. These lead to different data type precedence rules - I suspect a.answer is varchar(255). Also can't hurt to explicitly convert the first argument:
COALESCE(CONVERT(VARCHAR(MAX), a.answer),
r.textboxmulti, r.other, r.textbox, r.truefalse)
Could you explain what you mean by "all the data"? If you mean that it is not pulling data from r.textboxmulti for some rows, that mean that it is null for those rows and that fact is being masked by by the isnulls you have it wrapped in (incidentally, you could consider using a coalesce instead of nesting isnull....)
If you mean that it is getting data but leaving some of it off then one possibility is that it is being truncated. This can happen if SQL Server (or the next stage of processing where you are veiwing it...) sees it as a data type that is too small to hold the return value, this can sometimes happen due to implicit type conversions. You can deal with that by explicitly casting towards a large enough data type.
A final, rare, possibility is that r.textboxmulti containst an ascii null character. Many programs (including the SQL Server print command...) take that as a command to stop displaying anything from that string afterwards. This does not come up often, but I have encountered it myself.
In SQL Server management studio there is a setting that tells it how many characters to show for a column in the grid, or in text view.
If you're going to use the data in an application; are you seing all the data there? That is a sure sign that you use the default setting in SSMS to show only 255 characters.
I have a lot of difficulties in trying to translate this SQL query to a DQL one (I am using Symfony2).
SELECT d.* FROM Document d JOIN DocumentType dt ON dt.id = d.document_type_id WHERE (d.dateFinal - INTERVAL dt.renewal SECOND) > NOW();"
Thanks a lot !
Instead of database fields, you need to use the fields of you Document and DocumentType classes.
The join is done by naming the association field of your document (something like d.documenttype)
For those MySQL date functions: At least as far as I know, you would need to write custom DQL functions. Behind that link there is an example of an INTERVAL function. This might be the point where you want to execute the native SQL query instead.
SELECT d
FROM MyProject\Model\Document d
JOIN d.documenttype
WHERE [...your own DQL functions here...]
How do I convert this SQL query to LINQ-to-SQL?:
select
COUNT(ua.UserAlertID) as Alerts,
ph.LastName +' '+ ph.MiddleName as Name,
ph.Email,us.UserSystemID,
ur.UserStatus from PHUser ph
inner join UserSystem us on us.UserID=ph.UserID
inner join UserRole ur on ur.UserID=ph.UserID
inner join Role rr on rr.RoleID=ur.RoleID
inner join UserAlerts ua on ua.SeniorID=ph.UserID
group by ph.LastName,ph.MiddleName,ph.Email,us.UserSystemID,ur.UserStatus
I have converted most of the above query to LINQ but I got stuck to counting the number of values on the ua.UserAlertID column: COUNT(ua.UserAlertID) as Alerts.
How do I convert that to LINQ?
Kindly suggest How to convert COUNT(ua.UserAlertID) as Alerts in Linq??
Thanks
Can I see your converted LinQ?
If your Query is ok, you got a line like
group s by new {ua.UserAlertId,...,...} into temp.
as I remember in select new {} part use
select new
{
Total Alerts = temp.Key.UserAlertdId.Count(), ...,...,...,...
}
can you please try this and notify me?
A number of people can help you with this query. It's pretty straightforward. There is a product (very inexpensive) that can help you with these sorts of things. The product is Linqer (http://www.sqltolinq.com/). This tool will convert most SQL statements to Linq. There is a 30 day trial period and I think the cost is < $40. I have used it many times to get up to speed on converting SQL queries to Linq.
Then I might suggest you get a free product called LinqPad. This will allow you to prototype your Linq queries before pasting them into production code. It is a phenomenal tool.