Sum of revenue everyday, for last 30 days on each day - sql

I have a simple table.
Date | Revenue
5/1 12
5/2 25
5/3 93
.
.
11/15 47
I am trying to write a query that returns two columns. The first column is Date, day-by-day, like the original table. The second column is 30-Day-Revenue, which is the sum of the "Revenue" column in the original table for the last 30 days, ending on the displayed date. There is a lot of overlap when we sum. Thanks in advance!

I have an alternative solution (assumes your table is called revenue_table):
SELECT a.Date, SUM(b.Revenue)
FROM revenue_table a, revenue_table b
WHERE b.Date <= a.Date AND b.Date > a.Date - 30
GROUP BY a.Date;

SELECT table1.Date, table1.Revenue, Past30DayRevenue = SUM(table2.Revenue)
FROM insert_your_table_name_here table1
JOIN insert_your_table_name_here table2 ON DATEDIFF(day, table2.Date, table1.Date) BETWEEN 0 AND 29
GROUP BY table1.Date, table1.Revenue
ORDER BY table1.Date;

You can do this by using subqueries. E.g.
SELECT outer.date, (SELECT SUM(inner.revenue)
FROM table inner
WHERE inner.date > outer.date-30) AS thirtydayrevenue
FROM table outer

Related

How to retrieve only top rows per date

I am trying to extract first row per date from a balance table. and I am trying to write an sql code but I cant get a clue from how can I do it..
I tried max, sum, group by.. but its not helping out.
Date Account Balance
4/6/2019 A 90
4/5/2019 B 80
4/4/2019 C 70
4/3/2019 C 60
4/2/2019 D 80
4/1/2019 D 100
So how can I make a query which will show the following results?
Account Balance in April
Account Balance
A 90
B 80
C 70
D 80
use analytic function first_value if your dbms support
select Account,
FIRST_VALUE(balance) OVER (partition by Account ORDER BY date desc) AS balance
from table_name
First group by account to get the max date for each account and then join to the table:
select t.acount, t.balance
from tablename t inner join (
select account, max(date) maxdate
from tablename
group by account
) g on g.account = t.account and g.maxdate = t.date
you could use a sunquery for max date
select account, balance
from (
select accont, balance, max(date)
from my_table
group by accont, balance
) t
A canonical method would be filtering in the where clause:
select b.*
from balances b
where b.date = (select max(b2.date)
from balances b2
where b2.account = b.account and
b2.date >= '2019-04-01' and
b2.date < '2019-05-01'
);
Specific databases may have other approaches to this problem. The above generally has very good performance, particularly with an index on balances(account, date).

Sql- Count distinct values from date-30days to current register's date

I have 1 table named "Transactions" with the following columns: Date, ClientID, Amount.
I would like to have the active clients in the last 30 days.
Something like this:
Date | Active_Clients
2017/08/10 | 697
2017/08/11 | 710
2017/08/12 | 689
etc
Meaning: From 2017/08/10 minus 30 days to 2017/08/10 I had 697 active users.
I tryed many ways and didnt make it.
One method looks something like this:
select d.dte, count(distinct t.clientid)
from (select '2017-08-10' as dte union all
select '2017-08-11' as dte union all
select '2017-08-12' as dte
) d left join
transactions t
on t.date <= d.dte and t.date > d.dte - interval '30' day
group by d.dte
order by d.dte;
The exact syntax for date constants, date arithmetic, and subqueries with constant values differs by database.
Thank you guys for your help.
I think I managed to find the answer with #gordonlinoff 's answer.
select distinct data
, (select count(distinct id_cliente) from appvitaminas..transacoes B
where b.Data between DATEADD(day,-30,a.Data) and A.Data) Active_Clients
from appvitaminas..transacoes A
You can try this code to:
select distinct [Date]
, (select count(distinct B.clientid) from Transactions B
where b.Date between DATEADD(day,-30,a.Date) and A.Date) Active_Clients
from Transactions A

How to select all dates in SQL query

SELECT oi.created_at, count(oi.id_order_item)
FROM order_item oi
The result is the follwoing:
2016-05-05 1562
2016-05-06 3865
2016-05-09 1
...etc
The problem is that I need information for all days even if there were no id_order_item for this date.
Expected result:
Date Quantity
2016-05-05 1562
2016-05-06 3865
2016-05-07 0
2016-05-08 0
2016-05-09 1
You can't count something that is not in the database. So you need to generate the missing dates in order to be able to "count" them.
SELECT d.dt, count(oi.id_order_item)
FROM (
select dt::date
from generate_series(
(select min(created_at) from order_item),
(select max(created_at) from order_item), interval '1' day) as x (dt)
) d
left join order_item oi on oi.created_at = d.dt
group by d.dt
order by d.dt;
The query gets the minimum and maximum date form the existing order items.
If you want the count for a specific date range you can remove the sub-selects:
SELECT d.dt, count(oi.id_order_item)
FROM (
select dt::date
from generate_series(date '2016-05-01', date '2016-05-31', interval '1' day) as x (dt)
) d
left join order_item oi on oi.created_at = d.dt
group by d.dt
order by d.dt;
SQLFiddle: http://sqlfiddle.com/#!15/49024/5
Friend, Postgresql Count function ignores Null values. It literally does not consider null values in the column you are searching. For this reason you need to include oi.created_at in a Group By clause
PostgreSql searches row by row sequentially. Because an integral part of your query is Count, and count basically stops the query for that row, your dates with null id_order_item are being ignored. If you group by oi.created_at this column will trump the count and return 0 values for you.
SELECT oi.created_at, count(oi.id_order_item)
FROM order_item oi
Group by io.created_at
From TechontheNet (my most trusted source of information):
Because you have listed one column in your SELECT statement that is not encapsulated in the count function, you must use a GROUP BY clause. The department field must, therefore, be listed in the GROUP BY section.
Some info on Count in PostgreSql
http://www.postgresqltutorial.com/postgresql-count-function/
http://www.techonthenet.com/postgresql/functions/count.php
Solution #1 You need Date Table where you stored all date data. Then do a left join depending on period.
Solution #2
WITH DateTable AS
(
SELECT DATEADD(dd, 1, CONVERT(DATETIME, GETDATE())) AS CreateDateTime, 1 AS Cnter
UNION ALL
SELECT DATEADD(dd, -1, CreateDateTime), DateTable.Cnter + 1
FROM DateTable
WHERE DateTable.Cnter + 1 <= 5
)
Generate Temporary table based on your input and then do a left Join.

SQL - daily change in a value with business day into consideration

Hi I am trying to write a query that will track daily changes of a column which isn't populated on weekends/holidays.
First my data looks something like this :
Date Value
11/5/2015 10
11/6/2015 11
11/9/2015 12
11/10/2015 12
11/11/2015 11
so i want my query to give me result of the value change each date vs. the previous business day to return something like this:
Date Change in Value since previous business day
11/5/2015 -
11/6/2015 1
11/9/2015 1
11/10/2015 0
11/11/2015 -1
how do i write a write a query in MS Access which tracks daily changes over a business day? Currently i have written the following which only returns daily change over a calendar day as opposed to a biz day. so it won't return anything on Mondays.
SELECT A.Date, A.Value, ( A.Value - B.Value) as [Daily change]
FROM Table as A INNER JOIN Table as B on (A.date = B.date+1)
=============================================================================
thanks guys I've tried all 3 suggestions but they didn't work unfortunately :( there's another column called product ID and perhaps that is why? in other words, on each day, each product ID will have their own distinct values. there is a total of 100 product IDs so on each date there are 100 different values and I would like to track daily changes (business day basis) for each of the 100 product IDs. could anyone kindly help here? :(
It's hacky, but why not:
Join on 3 days ago also
use iif to say "if the 1 day ago diff is null then show the 3 days ago diff"
SELECT
A.Date, A.Value,
iif (isNull( A.Value - B.Value), ( A.Value - C.Value), ( A.Value - B.Value) ) as [change since last biz day]
FROM [Table] as A
left JOIN [Table] as B on ( A.Date = B.Date + 1 )
left JOIN [Table] as C on ( A.Date = C.Date + 3 )
Sometimes I just say it many times in English and the SQL follows. You want it where B equals the maximum date that is less than A.
SELECT A.Date,
A.Value,
A.Value - B.Value as [Daily Change]
FROM MyTable as A
INNER JOIN MyTable as B
ON B.date = (SELECT MAX(C.date) FROM MyTable C WHERE C.Date < A.Date)
ORDER BY A.Date

sql count statement with multiple date ranges

I have two table with different appointment dates.
Table 1
id start date
1 5/1/14
2 3/2/14
3 4/5/14
4 9/6/14
5 10/7/14
Table 2
id start date
1 4/7/14
1 4/10/14
1 7/11/13
2 2/6/14
2 2/7/14
3 1/1/14
3 1/2/14
3 1/3/14
If i had set date ranges i can count each appointment date just fine but i need to change the date ranges.
For each id in table 1 I need to add the distinct appointment dates from table 2 BUT only
6 months prior to the start date from table 1.
Example: count all distinct appointment dates for id 1 (in table 2) with appointment dates between 12/1/13 and 5/1/14 (6 months prior). So the result is 2...4/7/14 and 4/10/14 are within and 7/1/13 is outside of 6 months.
So my issue is that the range changes for each record and i can not seem to figure out how to code this.For id 2 the date range will be 9/1/14-3/2/14 and so on.
Thanks everyone in advance!
Try this out:
SELECT id,
(
SELECT COUNT(*)
FROM table2
WHERE id = table1.id
AND table2.start_date >= DATEADD(MM,-6,table1.start_date)
) AS table2records
FROM table1
The DATEADD subtracts 6 months from the date in table1 and the subquery returns the count of related records.
I think what you want is a type of join.
select t1.id, count(t2.id) as numt2dates
from table1 t1 left outer join
table2 t2
on t1.id = t2.id and
t2.startdate between dateadd(month, -6, t1.startdate) and t1.startdate
group by t1.id;
The exact syntax for the date arithmetic depends on the database.
Thank you this solved my issue. Although this may not help you since you are not attempting to group by date. But the answer gave me the insights to resolve the issue I was facing.
I was attempting to gather the total users a date criteria that had to be evaluated by multiple fields.
WITH data AS (
SELECT generate_series(
(date '2020-01-01')::timestamp,
NOW(),
INTERVAL '1 week'
) AS date
)
SELECT d.date, (SELECT COUNT(DISTINCT h.id) AS user_count
FROM history h WHERE h.startDate < d.date AND h.endDate > d.date
ORDER BY 1 DESC) AS total_records
FROM data d ORDER BY d.date DESC
2022-05-16, 15
2022-05-09, 13
2022-05-02, 13
...