I have a data set like this one below:
The result column is the sum of the value column of this row and the value column one row above the current row.
Is it possible to write a query for this result?
If your database does not support LAG, then we have some other options. In MySQL, we can try using a correlated subquery to find the lag value:
SELECT
id,
value,
COALESCE((SELECT t2.value FROM yourTable t2
WHERE t2.id < t1.id ORDER BY t2.id DESC LIMIT 1), 0) result
FROM yourTable t1;
A similar query would also work on SQL Server, using TOP 1 in the subquery.
You didn't tag your question with a specific rdbms, but most modern RDBMSs support the lag window function:
SELECT value + COALESCE(LAG(value) OVER (ORDER BY id), 0) AS result
FROM mytable
You can use lag() as in:
select t.*,
(value + lag(value) over (order by id)) as result
from t;
If you wanted a value for the first row, you can use sum() with a windowing clause:
select t.*,
sum(t.value) over (order by t.id rows between 1 preceding and current row) as result
from t;
This generalizes easily to more rows.
Or, if the ids have no gaps, then you can use join:
select t.*, (t.value + tprev.value) as result
from t left join
t tprev
on tprev.id = t.id - 1;
Related
My table looks something like this:
I want to get the record for the MAX Date. So after querying, my output should only contain this:
A correlated subquery is a simple method:
select t.*
from t
where t.update_date = (select max(t2.update_date) from t t2 where t2.number = t.num);
Use row_number() with top (1) with ties available for SQL Server (which was initially tagged) :
select top (1) with ties t.*
from table t
order by row_number() over (partition by no order by date desc);
You can also use subquery :
select t.*
from (select t.*, row_number() over (partition by no order by date desc) as seq
from table t
) t
where seq = 1;
I need to filter a SQL query based on a count of records within that query.
I want the query to return only the rows where the count of "Location" is greater than 5.
For example, we have 100 rows of data. 10 "Locations" make up all 100 rows, but I only want the rows where the COUNT("Location") > 5, essentially eliminating the rows with Locations where the COUNT("Location") < 5.
I've tried combinations of aggregation and the HAVING clause but can't nail down the answer.
I think you want a window function:
select t.*
from (select t.*, count(*) over (partition by location) as cnt
from t
) t
where cnt >= 5;
Alternative answer from Gordon Linoff using CTE:
with CTE as(
select *, count(*) over (partition by Location) as count from table
)
select *from CTE where count >= 5
Here is the solution you may have been after by using the HAVING clause...
select t.*
from t
inner join
(
select Location, count(*) as Count
from t
group by Location
having count(*) >= 5
) as t2 on t.Location = t2.Location
order by t.ID
Here it is in action.
I'm trying to extract some data were the Event column is distinct but I specifically want only rows that contain the highest number from the Value column, I'm thinking it's some mis-mash of using DISTINCT and GROUP BY but my sql knowledge is limited at the moment, any help would be great
Try this out:
SELECT [EVENT]
,MAX([Value])
FROM [MyTable]
GROUP BY [EVENT]
The easiest way to do this is using either a subquery or row_number():
select event, value
from (select t.*, row_number() over (partition by event order by value desc) as seqnum
from mytable t
) t
where seqnum = 1;
or:
select t.*
from mytable t
where t.value = (select max(t2.value) from mytable t2 where t2.event = t.event);
You should be careful about naming columns. event and value might be reserved words in some databases.
How about SELECT [EVENT], MAX([Value]) FROM [My Table] GROUP BY [EVENT] ?
You were on the right track.
select event, max(value)
from test
group by event
I am trying to get a running subtotal (understanding this is different from subtotals for groups, and the rollup approach).
Tried using
Row_Number() over (order by ID_Number) as Row_Count
and nesting it in select statements and using a LEFT OUTER JOIN on itself (which just churns).
What I am trying to get is this:
if ROW_COUNT > 1 THEN RUNNINGTOTAL = Volume_Category + (RUNNINGTOTAL for ID_Number where ROW_COUNT= ROW_COUNT(for this ID_Number*)-1)
I have a table with a list of unique "ID-Numbers" which are the focus here.
Unless you are using SQL Server 2012, the easiest way to do a cumulative sum is with a correlated subquery. Here is the template for the code:
select t.*,
(select sum(val) from t t2 where t2.ordercol <= t.ordercol) as cumesum
from t
In 2012, you can do:
select t.*,
sum(val) over (order by ordercol) as cumesum
from t
In both these, val is the column you want to sum and ordercol is how the ordering is specified.
Try this:
SELECT
T1.Id,
SUM(T2.Amount) Total
FROM tbl T1
JOIN Tbl T2
ON T1.Id>= T2.Id
GROUP BY T1.Id
I have a table that I want to calculate the average of one column but only for the last 10 rows.
SELECT AVG(columnName) as avg FROM tableName
I cannot apply top directly since this query only returns one row. I need a way to get the latest 10 rows and do the average on them.
Try this:
SELECT AVG(columnName) FROM
(SELECT TOP 10 columnName FROM tableName ORDER BY ColumnWhichHoldsOrder DESC) A
select avg(columnName)
from (
select columnName,
row_number() over (order by some column desc) as rn
from tableName
) t
where rn <= 10;