Linq to SQL equivalent of SUM GROUP BY SQL statement - sql

I'm having a hard time figuring out how to translate this simple SQL statement to (c#) linq to SQL :
SELECT table1.vat, SUM(table1.QTY * table2.FLG01 + table1.QTY * table2.FLG04)
FROM table1
inner join table2 on table2.key= table1.key
where '2010-02-01' <= table1.trndate and table1.trndate <= '2010-02-28'
Group by table1.vat
Any help is appreciated

I'm still learning LINQ but this seems to work
var result = from t1 in table1
from t2 in table2
where t1.key == t2.key && DateTime.Parse("2010-02-01") <= t1.trndate && t1.trndate <= DateTime.Parse("2010-02-28")
group new {t1,t2} by t1.vat into g
select new { vat = g.Key, sum = g.Sum(p => p.t1.QTY*p.t2.FLG01 + p.t1.QTY*p.t2.FLG04)};
I hope in translates well to LINQ to SQL because I only tried it on objects.

So with help of Jonas the above query reads this (using inner join):
var result = from t1 in table1
join t2 in table2 on t1.key equals t2.key
where DateTime.Parse("2010-02-01") <= t1.trndate && t1.trndate <= DateTime.Parse("2010-02-28")
group new {t1,t2} by t1.vat into g
select new { vat = g.Key, sum = g.Sum(p => p.t1.QTY*p.t2.FLG01 + p.t1.QTY*p.t2.FLG04)};

Related

how to convert postgres query looking for records where value appears only once to knex

I am trying to convert a postgres valid query that returns what I require to a knex query...
I keep getting various errors and can't write the knex query properly.
I have several versions of the query in postgres to find records in a table that appear only once and that have a specific user_id.
here are the different variants:
select * from project_authors t1
where (select count(*) from project_authors t2
where t1.project_id = t2.project_id) = 1
AND t1.user_id=2
OR
select * from project_authors t1
where NOT exists
(select 1 from project_authors t2
where t1.project_id = t2.project_id and t1.user_id <> t2.user_id) AND t1.user_id=2
OR
select * from project_authors t1
INNER JOIN (SELECT t3.project_id FROM project_authors t3 GROUP BY t3.project_id
HAVING COUNT (t3.project_id)=1) t2
ON t1.project_id=t2.project_id Where t1.user_id=2
the way I write the knex query is using parameters supplied in the request (for example):
const _readDbSingleAuthor = (table1, column1, criteria) => {
return db(`${table1} as t1`)
.select("*")
.where(
db(`${table1} as t2`)
.select("*")
.count("*")
.where(`t1.${column1}`, "=", `t2.${column1}`),
"=",
1
)
.andWhere(criteria);
I would appreciate any help...
the version above gave me a "maximum call stack exceeded" - so I hit the stackoverflow literally.
a version using join was the closest thing but gave me a result saying that the project_id column was ambiguous:
const _readDbSingleAuthor = (table1, data, column1, criteria) => {
return db
.select(data)
.from(`${table1} as t1`)
.join(
db
.select(column1)
.from(`${table1} as t3`)
.count(`${column1} as count`)
.groupBy(column1)
.having("t3.count", "=", 1)
.as("t2"),
`t2.${column1}`,
"=",
`t1.${column1}`
)
.where(criteria);
};

Is it possible to replace a cross apply with a join?

I am reverse engineering some legacy SQL algorithms to move to apache spark.
I have encountered a across apply which I understand is TSQL specific and there is no direct equivalent in ANSII or Spark SQL.
The sanitized algorithm is:
SELECT
Id_P ,
Monthindex ,
(
SELECT
100 * (STDEV(ResEligible.num_valid) / AVG(ResEligible.num_valid)) AS Pre_Coef_Var
FROM
tbl_p a CROSS APPLY
(
SELECT
e.Monthindex ,
e.num AS num_valid
FROM
dbo.tbl_p e
WHERE
e.Monthindex = a.MonthIndex
AND e.Id_P = a.Id_P
UNION ALL
SELECT DISTINCT
B1.[MonthIndex ] ,
Tr.num AS num_valid
FROM
#tbl_pr B1
INNER JOIN
#tbl_pr B2
ON
B1.[Id_P] = B2.[Id_P]
AND B2.Rang - B1.Rang BETWEEN 0 AND 2
INNER JOIN
dbo.tbl_p Tr
ON
Tr.Id_P = B1.Id_P
AND Tr.Monthindex = B1.Monthindex
WHERE
a.Id_P = B1.[Id_P]
AND B2.[MonthIndex] =
(
SELECT
MAX([MonthIndex])
FROM
#tbl_pr
WHERE
[MonthIndex] < a.MonthIndex
AND [Id_P] = a.Id_P) ) AS ResEligible
WHERE
a.Id_P = result.Id_P
AND a.MonthIndex = result.MonthIndex) AS Coeff
FROM
tbl_p AS result
WHERE
1 = 1
AND MonthIndex = #CurrentMonth
GROUP BY
Id_P ,
Monthindex) AS CC
so for every row in alias b we cross apply to the inner queries.
Is it possible to re-write the cross apply in terms of join operations (or otherwise) so I can re-implement in spark sql?
Cheers
Terry
Seems like you could rewrite your query as the below:
SELECT T1.col1,
T1.col2,
sq.col3Sum
FROM tbl1 T1
CROSS JOIN (SELECT SUM(T1sq.Col3) AS col3Sum
FROM tbl1 T1sq
JOIN tbl2 T2 ON T1sq.Col1 = T2.Col2
JOIN tbl3 T3 ON T2.col1 = T3.Col1) sq;
Seems odd, however, that there was no JOIN criteria between the 2 references to tbl1.

convert sql query to linq

I have this SQL query :
select RoleID
from tblUserRole
where UserID = 1
and RoleID in
(Select ID from tblGreenRole
Where
IsFullAccess = 1)
How can I convert this query to linq?
Something like this:
var result = (from t1 in context.tblUserRole
join t2 in context.tblGreenRole on t1.RoleID equals t2.ID
where t1.UserID == 1 && t2.IsFullAccess == 1).ToList();
If IsFullAccess is of type bit then change to && t2.IsFullAccess == true or just && t2.IsFullAccess

Nested self join, how can I fix it?

SQL can't cast those 2 tables together, does anyone know how to fix it?
select * from
(select ID from tbl_Message
WHERE ([From_User] = '38137F2C-591C-4BE6-91F8-F2C915F26066' OR [To_User] = '38137F2C-591C-4BE6-91F8-F2C915F26066')
AND [Replied_ID] = '00000000-0000-0000-0000-000000000000'
and deleted = 0 ) tbl1 inner join
(select top 1.Replied_ID as Reply_ID, Post_Date as Reply_Date from tbl_Message
where Replied_ID = tbl1.ID or ID = tbl1.ID
order by Post_Date desc) tbl2 on tbl2.Reply_ID =tbl1.ID
I am assuming you are unable to run query as structure is not correct I have updated your query try it.
select * from (
(select ID from tbl_Message
WHERE ([From_User] = '38137F2C-591C-4BE6-91F8-F2C915F26066' OR
[To_User] = '38137F2C- 591C- 4BE6-91F8-F2C915F26066')
AND [Replied_ID] = '00000000-0000-0000-0000-000000000000'
and deleted = 0 ) tbl1
inner join
(select top 1.Replied_ID as Reply_ID, Post_Date as Reply_Date from tbl_Message
where Replied_ID = tbl1.ID or ID = tbl1.ID
order by Post_Date desc) tbl2
on tbl2.Reply_ID =tbl1.ID ) as temp
if everything else you are doing is right it must work.

How to divide two values from the same column in SQL

As the title states I would like to divide two values with each other that are in the same column.
E.g.
A B C D
Shirts 2011 85 0
Shirts 2012 92 percent change from 2011 to 2012
Shirts 2013 100 percent change from 2012 to 2013
Pants 2011 31 0
Pants 2012 42 percent change from 2011 to 2012
Pants 2013 55 percent change from 2012 to 2013
Jacket 2011 10 0
Jacket 2012 16 percent change from 2011 to 2012
Jacket 2013 18 percent change from 2012 to 2013
In this example column D would be a derived from column C, where the value of 2012 is subtracted from 2011, and then times by a 100 to get the percent.
I don't know how to set the query up I tried doing a bunch of sub-queries but didn't know how to link them together. Any help would be greatly appreciated.
Here's an option to get what you're after
SELECT t1.a, t1.b, t1.c,
CASE WHEN t2.c IS NULL THEN 0 ELSE t1.c - t2.c END AS d,
CASE WHEN t2.c IS NULL THEN 0 ELSE (1.0 * t1.c - t2.c) / t1.c * 100.0 END AS pct
FROM t t1
LEFT OUTER JOIN t t2 ON t1.a = t2.a
AND t1.b = t2.b + 1
SQL Fiddle Example
If I'm understanding your requirements correctly, you could use a recursive cte to accomplish your results. This uses ROW_NUMBER() and partitions by (groups by) column A.
This method would best work if you can't guarantee sequential years in column B. If you always have sequential years, then bobs provides the best alternative.
with cte as (
select A, B, C,
ROW_NUMBER() OVER (PARTITION BY A ORDER BY B) rn
from yourtable
),
recursive_cte as (
select A, B, C, 0 prc
from cte
where rn = 1
union all
select y.A, y.B, y.C, y.C-c.C prc
from cte y
join cte c on y.a=c.a and y.rn=c.rn+1
)
select *
from recursive_cte
order by a, b
SQL Fiddle Demo
This will return the difference between each year and the previous grouped by column A. It uses a 2nd CTE just for simplicity. If you want the actual percent changed, update the formula above.
--EDIT
Since it sounds like you're looking for percentage growth, try replacing y.C-c.C prc with this formula instead:
cast(y.C as decimal(10,2))/cast(c.C as decimal(10,2))
Use CAST if your data types are integers.
You can accomplish this with a self-join:
SELECT curr.ClothingType, curr.SalesYear, curr.NumberSold
, COALESCE((CAST((curr.NumberSold - prev.NumberSold) AS NUMERIC(5,2)) / prev.NumberSold) * 100, 0) AS PercentChange
FROM #Clothes AS curr
LEFT JOIN #Clothes AS prev ON curr.ClothingType = prev.ClothingType
AND curr.SalesYear = prev.SalesYear + 1
SQL Fiddle Example
I agree with Shivan, but only because I don't know how to do it without PHP. With PHP it's just a matter of pulling the two totals, doing the math and sending a query back with the answers.
ALSO BE SURE TO READ THIS BECAUSE IT'S THE MORE IMPORTANT PART
Your math's wrong. (Shirts2011 - Shirts2012) * 100 doesn't give you the percent change. It just gives you 100 times the difference of the two (actually, the negative difference based on your wording). What you want, math-wise, is:
((Item2012-Item2011)/Item2011)*100
I know the outside parens aren't necessary but they make it easier to read. The percent change is the same as 100 times the ratio of the difference of the two to the initial.
Edited to add PHP code.
The PHP looks gross, but it gets the job done.
$conn = new PDO(HOST:DATABASE, USERNAME, PASSWORD);
$query = "SELECT A, B, C FROM yourTable";
$st = $conn->prepare($query);
$st->execute();
$list = array();
while($row = $st->fetch(PDO::FETCH_ASSOC))
$list[] = $row;
$fill = array();
for($i=1; $i<count($list); $i++)
if($list[$i]['A'] == $list[$i-1][A])
$fill[] = $array('A' => $list[$i]['A'],
'B' => $list[$i]['B'],
'D' => ($list[$i]['C']-$list[$i-1]['C'])/$list[$i-1]['C']*100);
$update = new PDO(HOST:DATABASE, USERNAME, PASSWORD);
for($i=0; $i<count($fill); $i++){
$query = "UPDATE yourTable SET D = " . $fill[$i]['D'] . " WHERE A = " . $fill[$i]['A'] . " AND B = " . $fill[$i]['B'];
$st = $update->prepare($query);
$st->execute();
}
Just initialize your table where the 2011 D columns = 0.
UPDATE yourTable SET D = 0 WHERE B = 2011;
And before the flames start, I know a foreach would have worked; I just think a standard for looks better (and allows you to skip the first 2011 value).
Try this:
SELECT t1.type A, t1.year B, t1.value C,
IF(
EXISTS(
SELECT 1 FROM table t2 WHERE t1.type = t2.type AND t1.year = (t2.year - 1)
),
((SELECT t3.year FROM table t3 WHERE t1.type = t3.type AND t1.year = (t3.year - 1)) - t1.year)/t1.year,
0
) D
FROM table t1
Not super efficient, but it can be done.
You could try this too:
UPDATE mytable t1
INNER JOIN mytable t2
ON t1.A = t2.A AND t2.B = t1.B - 1
SET t1.D = ((t1.C - t2.C) / t2.C) * 100;
see fiddle.
Assuming you already have 0 as a default for D. If not, just set it to 0 for all rows before running this query.
Try this:
select Y2013.*, Y2012.C, Y2013.C, Y2013.C/Y2011.C
from (
select * from data where B = year(getdate())
) Y2013
left join (
select * from data where B = year(getdate()) - 1
) Y2012 on Y2012.A = Y2013.A
left join (
select * from data where B = year(getdate()) - 2
) Y2011 on Y2011.A = Y2012.A
and Y2011.A = Y2013.A