sql query group by day of month - sql

I have a record table that icludes dates of rows created. (oracle db)
ID City CreateDate
1 city-1 12.12.2017
1 city-2 13.12.2017
1 city-1 13.12.2017
1 city-3 12.12.2017
....
....
I want to create a daiy report in a month. For example City-1 report by days in December
Day Count
1 10
2 80
3 60
4 10
...
30 11

I think you can use extract with count functions:
SELECT EXTRACT(day FROM CreateDate) "Day",
COUNT(CreateDate) "Number of Reports"
FROM yourTableName
GROUP BY EXTRACT(day FROM CreateDate)
ORDER BY "Number of Reports" ASC;

If I understood it correctly, the following query will generate the report you wanted for December.
SELECT EXTRACT(day FROM CreateDate) "Day", COUNT(*) "Count" FROM your_record_table WHERE EXTRACT(month FROM CreateDate) = 12 GROUP BY EXTRACT(day FROM CreateDate) ORDER BY EXTRACT(day FROM CreateDate);

Related

SQL Bigquery Counting repeated customers from transaction table

I have a transaction table that looks something like this.
userid
orderDate
amount
111
2021-11-01
20
112
2021-09-07
17
111
2021-11-21
17
I want to count how many distinct customers (userid) that bought from our store this month also bought from our store in the previous month. For example, in February 2020, we had 20 customers and out of these 20 customers 7 of them also bought from our store in the previous month, January 2020. I want to do this for all the previous months so ending up with something like.
year
month
repeated customers
2020
01
11
2020
02
7
2020
03
9
I have written this but this only works for only the current month. How would I iterate or rewrite it to get the table as shown above.
WITH CURRENT_PERIOD AS (
SELECT DISTINCT userid
FROM table1
WHERE DATE(orderDate) BETWEEN DATE_TRUNC(CURRENT_DATE(),MONTH) AND DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)
),
PREVIOUS_PERIOD AS (
SELECT DISTINCT userid
FROM table1
WHERE DATE(orderDate) BETWEEN DATE_TRUNC(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH),MONTH) AND LAST_DAY(DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH))
)
SELECT count(1)
FROM CURRENT_PERIOD RC
WHERE RC.userid IN (SELECT DISTINCT userid FROM PREVIOUS_PERIOD)
You can summarize to get one record per month, use lag(), and then aggregate:
select yyyymm,
countif(prev_yyyymm = date_add(yyyymm, interval -1 month)
from (select userid, date_trunc(order_date, month) as yyyymm,
lag(date_trunc(order_date, month)) over (partition by userid order by date_trunc(order_date, month)) as prev_yyyymm
from table1
group by 1, 2
) t
group by yyyymm
order by yyyymm;

SQL Count Entries for each Month of the last 6 Months

I got a problem while trying to count the entries that were created in a month for the last 6 months.
The table looks like this:
A B C D
Year Month Startingdate Identifier
-----------------------------------------
2019 3 2019-03-12 OAM_1903121
2019 2 2019-03-21 OAM_1902211
And the result should look like:
A B C
Year Month Amount of orders
---------------------------------
2019 3 26
2019 2 34
This is what I have so far, but it doesn't get me the proper results:
SELECT year, month, COUNT(Startingdate) as Amount
FROM table
WHERE Startingdate > ((TRUNC(add_months(sysdate,-3) , 'MM'))-1)
GROUP BY year, month
I have not tested it, but it should work:
select year, month, count(Stringdate) as Amount_of_order
from table
where Stringdate between add_months(sysdate, -6) and sysdate
group by year, month;
Let me know.
Try that :
SELECT YEAR(Startingdate) AS [Year], MONTH(Startingdate) AS [Month], COUNT(*) AS Amount
FROM table
WHERE Startingdate > DATEADD(MONTH, -6, GETDATE())
GROUP BY YEAR(Startingdate), MONTH(Startingdate)
ORDER BY YEAR(Startingdate), MONTH(Startingdate) DESC
I think your issue is the filtering. If so, this should handle the most recent six full months:
SELECT year, month, COUNT(*) as num_orders
FROM table
WHERE Startingdate >= TRUNC(add_months(sysdate, -6) , 'MM')
GROUP BY year, month;

how to count a column by month if the date column has time stamp?

I have two columns in a table:
id date
1 1/1/18 12:55:00 AM
2 1/2/18 01:34:00 AM
3 1/3/18 02:45:00 AM
How do I count the number of IDs per month if the time is appended into the date column?
The output would be:
Count month
3 1
In ANSI SQL, you would use:
select extract(month from date) as month, count(*)
from t
group by extract(month from date);
I think more databases support a month() function rather than extract(), though.
you have to extract month and count by using group by
select DATE_PART('month', date) as month,count(id) from yourtable
group by DATE_PART('Month', date)

Find number of repeating visitors in a month - PostgreSQL

I am using PostgreSQL and my data looks something like this:
UserID TimeStamp
1 2014-02-03
2 2014-02-03
3 2014-02-03
1 2014-03-03
2 2014-03-03
6 2014-03-03
7 2014-03-03
This is just dummy data for 2 days in which some UserID is getting repeated on both the days. I would like to find out the number of repeated UserId every month. For this example the final result set should look like:
Count Year Month
0 2014 2
2 2014 3
In the above table, March 3014 has 2 repeat UserID and Feb 2014 has none.
I can find out the distinct UserID for each month but not the repeated UserID. Any help in this regard would be much appreciated.
select
count(distinct userid) as "Count",
extract(year from t0.timestamp) as "Year",
extract(month from t0.timestamp) as "Month"
from
t t1
inner join
t t0 using (userid)
where t0.timestamp < date_trunc('month', t1.timestamp)
group by 2, 3
or may be faster
select
count(distinct userid) as "Count",
extract(year from t0.timestamp) as "Year",
extract(month from t0.timestamp) as "Month"
from t t1
where exists (
select 1
from t
where
userid = t1.userid
and
timestamp < date_trunc('month', t1.timestamp)
)
group by 2, 3
This might work, have not tested it out yet.
SELECT
COUNT(DISTINCT(UserId))
, EXTRACT(YEAR FROM TIMESTAMP TimeStamp) AS Year
, EXTRACT(MONTH FROM TIMESTAMP Timestamp) AS Month
FROM TABLE
GROUP BY TimeStamp
To rephrase your question:
How many users are not new (i.e. already visited the shop/website/whatever in a previous month) for each month?
SELECT
yr, mon,
COUNT(*) AS all_users,
COUNT(*) - SUM(repeated) AS new_users,
SUM(repeated) AS existing_users
FROM
(
SELECT UserId,
EXTRACT(YEAR FROM TimeStamp) AS yr,
EXTRACT(MONTH FROM TimeStamp) AS mon,
CASE WHEN ROW_NUMBER() -- 1st time users get 0
OVER (PARTITION BY UserId
ORDER BY EXTRACT(YEAR FROM TimeStamp) ,
EXTRACT(MONTH FROM TimeStamp)) = 1
THEN 0
ELSE 1
END AS repeated
FROM vt
GROUP BY UserId,
EXTRACT(YEAR FROM TimeStamp),
EXTRACT(MONTH FROM TimeStamp)
) AS dt
GROUP BY yr,mon
ORDER BY 1,2
The inner GROUP BY is needed if there are multiple rows for a user within the same month.
Is this what you want?
select yyyymm, sum(case when cnt > 1 then 1 else 0 end) as dupcnt
from (select to_char(timestamp, 'YYYY-MM') as yyyymm, userid, count(*) as cnt
from table t
group by to_char(timestamp, 'YYYY-MM'), userid
) t
group by yyyymm
order by yyyymm;

Need to find Average of top 3 records grouped by ID in SQL

I have a postgres table with customer ID's, dates, and integers. I need to find the average of the top 3 records for each customer ID that have dates within the last year. I can do it with a single ID using the SQL below (id is the customer ID, weekending is the date, and maxattached is the integer).
One caveat: the maximum values are per month, meaning we're only looking at the highest value in a given month to create our dataset, thus why we're extracting month from the date.
SELECT
id,
round(avg(max),0)
FROM
(
select
id,
extract(month from weekending) as month,
extract(year from weekending) as year,
max(maxattached) as max
FROM
myTable
WHERE
weekending >= now() - interval '1 year' AND
id=110070 group by id,month,year
ORDER BY
max desc limit 3
) AS t
GROUP BY id;
How can I expand this query to include all ID's and a single averaged number for each one?
Here is some sample data:
ID | MaxAttached | Weekending
110070 | 5 | 2011-11-10
110070 | 6 | 2011-11-17
110071 | 4 | 2011-11-10
110071 | 7 | 2011-11-17
110070 | 3 | 2011-12-01
110071 | 8 | 2011-12-01
110070 | 5 | 2012-01-01
110071 | 9 | 2012-01-01
So, for this sample table, I would expect to receive the following results:
ID | MaxAttached
110070 | 5
110071 | 8
This averages the highest value in a given month for each ID (6,3,5 for 110070 and 7,8,9 for 110071)
Note: postgres version 8.1.15
First - get the max(maxattached) for every customer and month:
SELECT id,
max(maxattached) as max_att
FROM myTable
WHERE weekending >= now() - interval '1 year'
GROUP BY id, date_trunc('month',weekending);
Next - for every customer rank all his values:
SELECT id,
max_att,
row_number() OVER (PARTITION BY id ORDER BY max_att DESC) as max_att_rank
FROM <previous select here>;
Next - get the top 3 for every customer:
SELECT id,
max_att
FROM <previous select here>
WHERE max_att_rank <= 3;
Next - get the avg of the values for every customer:
SELECT id,
avg(max_att) as avg_att
FROM <previous select here>
GROUP BY id;
Next - just put all the queries together and rewrite/simplify them for your case.
UPDATE: Here is an SQLFiddle with your test data and the queries: SQLFiddle.
UPDATE2: Here is the query, that will work on 8.1 :
SELECT customer_id,
(SELECT round(avg(max_att),0)
FROM (SELECT max(maxattached) as max_att
FROM table1
WHERE weekending >= now() - interval '2 year'
AND id = ct.customer_id
GROUP BY date_trunc('month',weekending)
ORDER BY max_att DESC
LIMIT 3) sub
) as avg_att
FROM customer_table ct;
The idea - to take your initial query and run it for every customer (customer_table - table with all unique id for customers).
Here is SQLFiddle with this query: SQLFiddle.
Only tested on version 8.3 (8.1 is too old to be on SQLFiddle).
8.3 version
8.3 is the oldest version I've got access to, so I can't guarantee it'll work in 8.1
I'm using a temporary table to work out the best three records.
CREATE TABLE temp_highest_per_month as
select
id,
extract(month from weekending) as month,
extract(year from weekending) as year,
max(maxattached) as max_in_month,
0 as priority
FROM
myTable
WHERE
weekending >= now() - interval '1 year'
group by id,month,year;
UPDATE temp_highest_per_month t
SET priority =
(select count(*) from temp_highest_per_month t2
where t2.id = t.id and
(t.max_in_month < t2.max_in_month or
(t.max_in_month= t2.max_in_month and
t.year * 12 + t.month > t2.year * 12 + t.month)));
select id,round(avg(max_in_month),0)
from temp_highest_per_month
where priority <= 3
group by id;
The year & month are included in the working out the priority so that if two months have the same maximum, they'll still be included in the numbering correctly.
9.1 version
Similar to Igor's answer, but I used the With clause to split the steps.
with highest_per_month as
( select
id,
extract(month from weekending) as month,
extract(year from weekending) as year,
max(maxattached) as max_in_month
FROM
myTable
WHERE
weekending >= now() - interval '1 year'
group by id,month,year),
prioritised as
( select id, month, year, max_in_month,
row_number() over (partition by id, month, year
order by max_in_month desc)
as priority
from highest_per_month
)
select id, round(avg(max_in_month),0)
from prioritised
where priority <= 3
group by id;