I have a dataset in the format of: Date Amount such as:
Date Amount
2018-01 100
2018-02 200
2018-03 300
I want the sum year to date at the end of each month resulting in:
Date Amount
2018-01 100
2018-02 300 (100+200)
2018-03 600 (100+200+300)
How do I go about referencing the previous year-to-date sum in the previous row?
You can do this with a window function:
select date,
sum(amount) over (order by date) as so_far
from the_table
order by date;
The above is ANSI standard SQL
You need to use Running Total for this.
SELECT
Date,
SUM (Amount) OVER (ORDER BY Date ASC) AS RunningAmount
FROM Table1
Order by Date asc;
You can use OVER clause for that. Try as below.
Use PARTITION BY DATEPART(yy, Date) if you want to separate cumulative total for each year as below.
SELECT Date, Amount, SUM(Amount) OVER (PARTITION BY DATEPART(yy, Date) ORDER BY DATEPART(mm, Date)) AS CumulativeTotal
FROM Table
Or if you want to have cumulative total for all years then remove PARTITION BY DATEPART(yy, Date) part. Just order by is enough.
SELECT Date, Amount, SUM(Amount) OVER (ORDER BY Date) AS CumulativeTotal
FROM Table
Refer this for more information. Producing a moving average and cumulative total
Other option would to use a correlated subquery :
select t.*,
(select sum(t1.amount) from table t1 where t1.date <= t.date) as amount
from table t;
This would work almost in all DBMS.
Related
I am attempting to produce Table2 below - which essentially counts the rows that have the same day and adds up the "amount" column for the rows that are on the same day.
I found a solution online that can count entries from the same day, which works:
SELECT
DATE_TRUNC('day', datetime) AS date,
COUNT(datetime) AS date1
FROM Table1
GROUP BY DATE_TRUNC('day', datetime);
It is partially what I am looking for, but I am having difficulty trying to display all the column names.
In my attempt, I have all the columns I want but the Accumulated Count is not accurate since it counts the rows with unique IDs (because I put "id" in GROUP BY):
SELECT *, count(id) OVER(ORDER BY DateTime) as accumulated_count,
SUM(Amount) OVER(ORDER BY DateTime) AS Accumulated_Amount
FROM Table1
GROUP BY date(datetime), id
I've been working on this for days and seemingly have come across every possible outcome that is not what I am looking for. Does anyone have an idea as to what I'm missing here?
Cumulative sum and count should be calculated for each day
with Table1 (id,datetime,client,product,amount) as(values
(1 ,to_timestamp('2020-07-08 07:30:10','YYYY-MM-DD HH24:MI:SS'),'Tom','Bill Payment',24),
(2 ,to_timestamp('2020-07-08 07:50:30','YYYY-MM-DD HH24:MI:SS'),'Tom','Bill Payment',27),
(3 ,to_timestamp('2020-07-09 08:20:10','YYYY-MM-DD HH24:MI:SS'),'Tom','Bill Payment',37)
)
SELECT
Table1.*,
count(*) over (partition by DATE_TRUNC('day', datetime)
order by datetime asc ) accumulated_count,
sum(amount) over (partition by DATE_TRUNC('day', datetime) order by datetime asc) accumulated_sum
FROM Table1;
Not to familiar with postgresql but this does what you ask fror.
with data (id,date_time,client,product,amount) as(
select 1 ,to_timestamp('Jul 08 2020, 07:30:10','Mon DD YYYY, HH24:MI:SS'),'Tom','Bill',24 Union all
select 2 ,to_timestamp('Jul 08 2020, 07:50:30','Mon DD YYYY, HH24:MI:SS'),'Tom','Bill',27 Union all
select 3 ,to_timestamp('Jul 09 2020, 08:20:10','Mon DD YYYY, HH24:MI:SS'),'Tom','Bill',37
)
select d.id,d.date_time,d.client,d.product,d.amount,
(select count(*) from data d1
where d1.date_time <= d.date_time and date(d1.date_time) = date(d.date_time) ) acc_count,
(select sum(amount) from data d1
where d1.date_time <= d.date_time and date(d1.date_time) = date(d.date_time) ) acc_amount
from data d
So, the query is simple but i am facing issues in implementing the Sql logic. Heres the query suppose i have records like
Phoneno Company Date Amount
83838 xyz 20210901 100
87337 abc 20210902 500
47473 cde 20210903 600
Output expected is past 7 days progress as running avg of amount for each date (current date n 6 days before)
Date amount avg
20210901 100 100
20210902 500 300
20210903 600 400
I tried
Select date, amount, select
avg(lg) from (
Select case when lag(amount)
Over (order by NULL) IS NULL
THEN AMOUNT
ELSE
lag(amount)
Over (order by NULL) END AS LG)
From table
WHERE DATE>=t.date-7) as avg
From table t;
But i am getting wrong avg values. Could anyone please help?
Note: Ive tried without lag too it results the wrong avgs too
You could use a self join to group the dates
select distinct
a.dt,
b.dt as preceding_dt, --just for QA purpose
a.amt,
b.amt as preceding_amt,--just for QA purpose
avg(b.amt) over (partition by a.dt) as avg_amt
from t a
join t b on a.dt-b.dt between 0 and 6
group by a.dt, b.dt, a.amt, b.amt; --to dedupe the data after the join
If you want to make your correlated subquery approach work, you don't really need the lag.
select dt,
amt,
(select avg(b.amt) from t b where a.dt-b.dt between 0 and 6) as avg_lg
from t a;
If you don't have multiple rows per date, this gets even simpler
select dt,
amt,
avg(amt) over (order by dt rows between 6 preceding and current row) as avg_lg
from t;
Also the condition DATE>=t.date-7 you used is left open on one side meaning it will qualify a lot of dates that shouldn't have been qualified.
DEMO
You can use analytical function with the windowing clause to get your results:
SELECT DISTINCT BillingDate,
AVG(amount) OVER (ORDER BY BillingDate
RANGE BETWEEN TO_DSINTERVAL('7 00:00:00') PRECEDING
AND TO_DSINTERVAL('0 00:00:00') FOLLOWING) AS RUNNING_AVG
FROM accounts
ORDER BY BillingDate;
Here is a DBFiddle showing the query in action (LINK)
How to write SQL query that will sum the amount from the previous days/years. Like from the start.
Scenario I want to compute accumulated sales of the store from the day it was opened.
Example
SELECT SUM(AMOUNT)
FROM TransactionTable
WHERE TransactionDate = ???
The plan that I have is to query on this table and get the oldest transaction date record, then I will use that in the WHERE condition. Do you think that it is the best solution?
You can try below using having min(transaction) which will give you the date when transaction first started
select sum (amt) from
(
SELECT SUM(AMOUNT) as amt from TransactionTable
group by TransactionDate
having TransactionDate between min(TransactionDate) and getdate()
)A
To compute accumulated sales of the store from the day it started you can use SUM with OVER clause
SELECT TransactionDate, SUM(AMOUNT) OVER (ORDER BY TransactionDate) AS AccumulatedSales
FROM TransactionTable
use group by TransactionDate
SELECT convert(date,TransactionDate), SUM(AMOUNT) from TransactionTable
group by convert(date,TransactionDate)
I want the selected data in below format.
TOTAL_FEE WEEK
+---------------+--------------+
24000 WEEK_1
24000 WEEK_2
24000 WEEK_3
My query that give me result groupby date is :
select count(*) * 24000, CAST(p.submited_date AS DATE)
from Form_For_Business_Name_Registration p
where p.STATUS !='NS'
and CAST(p.submited_date AS DATE)>='2016-01-22'
and CAST(p.submited_date AS DATE)<='2016-03-04'
GROUP BY CAST(p.submited_date AS DATE)
What i want is to get results groupby weeks but weeks should be calculated from the given date range.
Note : if there is no data for the week it should return 0 counts for that week.
Will somebody guide me to write a SQL query to get desired output.
Thank you!
You can use DATEPART, like:
DATEPART(week, submited_date)
I would advise using the week number and year number (similar to MySQL's WeekYear) in order to ensure the grouping is specific to that year's week.
You can take the difference to calculate weeks:
select count(*) * 24000,
(DATEDIFF(day, CAST(p.submited_date AS DATE), '2016-01-22') / 7) as weeknum
from Form_For_Business_Name_Registration p
where p.STATUS <> 'NS' and
CAST(p.submited_date AS DATE) >= '2016-01-22' and
CAST(p.submited_date AS DATE) <= '2016-03-04'
group by (DATEDIFF(day, CAST(p.submited_date AS DATE), '2016-01-22') / 7);
Try this (if I understood what you want)
GROUP BY DATEPART(wk, p.submited_date)
I recommed using calendar table...Below is the sample query output from calendar table..once you have the table,all you need to do is join two tables and filter rows...
EX:
create table
#test
(
tt datetime
)
insert into #test
select dateadd(day,-n,getdate())
from numbers
where n<10
select
* from
#test
---now if i want to find which week those fall,all i have to do is join calendar table
select
tt,wkno
from
#test t1
join
calendar c
on c.date=t1.tt
I have an SQLite database which contains transactions, each of them having a price and a transDate.
I want to retrieve the sum of the transactions grouped by month. The retrieved records should be like the following:
Price month
230 2
500 3
400 4
it is always good while you group by MONTH it should check YEAR also
select SUM(transaction) as Price,
DATE_FORMAT(transDate, "%m-%Y") as 'month-year'
from transaction group by DATE_FORMAT(transDate, "%m-%Y");
FOR SQLITE
select SUM(transaction) as Price,
strftime("%m-%Y", transDate) as 'month-year'
from transaction group by strftime("%m-%Y", transDate);
You can group on the start of the month:
select date(DateColumn, 'start of month')
, sum(TransactionValueColumn)
from YourTable
group by
date(DateColumn, 'start of month')
Try the following:
SELECT SUM(price), strftime('%m', transDate) as month
FROM your_table
GROUP BY strftime('%m', transDate);
Use the corresponding page in SQLite documentation for future references.
SELECT
SUM(Price) as Price, strftime('%m', myDateCol) as Month
FROM
myTable
GROUP BY
strftime('%m', myDateCol)
This another form:
SELECT SUM(price) AS price,
STRFTIME('%Y-%m-01', created_at) as created_at
FROM records
GROUP BY STRFTIME('%Y-%m-01', created_at);
Another way is to substring the year and the month from the column and group by them. Assuming the format it's like 2021-05-27 12:58:00 you can substract the first 7 digits:
SELECT
substr(transDate, 1, 7) as YearMonth
SUM(price) AS price
FROM
records
GROUP BY
substr(transDate, 1, 7);
In Sqlite, if you are storing your date in unixepoch format, in seconds:
select count(myDate) as totalCount,
strftime('%Y-%m', myDate, 'unixepoch', 'localtime') as yearMonth
from myTable group by strftime('%Y-%m', myDate, 'unixepoch', 'localtime');
If you are storing the date in unixepoch format, in milliseconds, divide by 1000:
select count(myDate/1000) as totalCount,
strftime('%Y-%m, myDate/1000, 'unixepoch', 'localtime') as yearMonth
from myTable group by strftime('%Y-%m, myDate/1000, 'unixepoch', 'localtime');