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

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

Related

How to do query on multiple dates on certain range on Google Big Query

I'm doing quite long query to find a customer with certain condition on certain dates, in this case '2019-6-20', the query is like this
Here's my code
select current_date() as date , count(customer_id) as cell13
from(
select customer_id, count(id) as total, string_agg(payment_state order by created_at desc limit 1) as cek
from(
select distinct(A.id), A.customer_id, extract(month from A.created_at) as months,extract(day from A.created_at) as days, extract(year from A.created_at) as years, payment_state, A.created_at, A.grandtotal_cents
from bl.orders as A
left join bl.blacklists as B
on A.customer_id = B.customer_id
where date(A.created_at) >= date_sub(date('2019-6-20') , interval 60 day) and grandtotal_cents > 0 and B.customer_id is null
)
group by customer_id
having cek = "unpaid")
Here's the result
Row date cell13
1 2019-06-21 696
Now I need to query this to multiple dates in certain date range, for example 2019-03-23 to 2019-06-21. How suppose I do this, so the output will like
Row date cell13
1 2019-06-21 696
...
90 2019-03-23 ...
You can generate a table of dates using generate_date_array() and unnest() and then use this with a left join.
Overall, though, your query is a message an hard to follow, but here is the idea:
with dates as (
select dte
from (select generate_date_array('2019-03-23', '2016-06-21', interval 1 day) d
) d cross join
unnest(d.d) dte
)
select . . .
from dates left join
bl.orders o
on date(o.created_at) >= date_sub(dte, interval 60 day)
. . .

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).

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 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
...

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

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