order by month oracle - sql

I'm trying to make a simple query to find the average car sales per month from a table called "salestransaction".
My code:
select to_char(st.dateofsale, 'MON') as mnth, count(*) / 2 as Average_Car_Sales
from salestransaction st
group by to_char(st.dateofsale, 'MON')
order by to_char(st.dateofsale, 'MON');
My order by month is not outputting the correct order.
What can I do to make it output by month? starting from JAN - DEC?
Thank you.

An easy approach is to add month number to group by, then order by this field:
select to_char(st.dateofsale, 'MON') as mnth,
count(*) / 2 as Average_Car_Sales
from salestransaction st
group by EXTRACT(month FROM st.dateofsale),
to_char(st.dateofsale, 'MON')
order by EXTRACT(month FROM st.dateofsale);
If you try to order without aggregate function or without adding month number in group by expression then you will get ORA-00979: not a GROUP BY expression error
To avoid Extract you can use to_char with MM pattern:
select to_char(st.dateofsale, 'MON') as mnth,
count(*) / 2 as Average_Car_Sales
from salestransaction st
group by to_char(st.dateofsale, 'MM'),
to_char(st.dateofsale, 'MON')
order by to_char(st.dateofsale, 'MM');

My recommendation:
order by min(st.dateofsale);
That is, just pull a value out for each group and use that for the ordering.
If you have data from multiple years, the above might not work. Instead:
order by min(extract(month from st.dateofsale))

It is because you order them according to the month name in this case, december comes before january. You need to get their numeric values.
Here is an example from oracle documantation:
SELECT EXTRACT(month FROM order_date) "Month",
COUNT(order_date) "No. of Orders"
FROM orders
GROUP BY EXTRACT(month FROM order_date)
ORDER BY EXTRACT(month FROM order_date)
You can check it from this link for more detailed information:
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions050.htm

Related

Select and Count Multiple Group By SQL

Can someone tell me how to do this in Database?
I've tried some sql like:
SELECT disastertype, YEAR(eventdate) as year,
COUNT(disastertype) AS disastertype_total
FROM v_disasterlogs_all
WHERE YEAR(eventdate) >= year(CURRENT_TIMESTAMP) - 4
GROUP BY YEAR(eventdate)
ORDER BY YEAR(eventdate) ASC
But, it only shows like this:
include disastertype on our group by statement.
SELECT disastertype, YEAR(eventdate) as year,
COUNT(disastertype) AS disastertype_total
FROM v_disasterlogs_all
WHERE YEAR(eventdate) >= year(CURRENT_TIMESTAMP) - 4
GROUP BY YEAR(eventdate), disastertype
ORDER BY YEAR(eventdate) ASC
I am assuming you want a count (the column index) to be associated with each unique year?
In this case, a possible solution in postgres will be as below.
select
dense_rank() over (order by date_part('year', (eventdate))) as index ,
date_part('year', (eventdate)) as year,
disastertype,
count(disastertype)
from
v_disaterlogs_all
where
date_part('year', (eventdate)) >= date_part('year', now()) - 4
group by
year,
disastertype
order by
year asc;
In postgres, I have used the function date_part to extract the year from the timestamp.
Working solution on dbfiddle.

Order By Month Name - Postgresql

I followed this post Order by using month name in PostgreSQL but not success!
I have a query (its working) and I just need to order the results by mont name. This is thr query I am using:
select to_char(purchase_date, 'Month') as mes_2021,
sum(gmv::float4) as soma_gmv
from tablename
where purchase_date > '2021-01-01'
GROUP BY mes_2021
I am trying:
order by to_date(purchase_date, 'Month') - No success
order by date_part(purchase_date::date, 'Month') - No success
If i use order by mes_2021
One trick is to use a window function on the date:
select to_char(purchase_date, 'Month') as mes_2021,
sum(gmv::float4) as soma_gmv
from tablename
where purchase_date > '2021-01-01'
group by mes_2021
order by min(purchase_date);
This, of course, assumes that the dates are all in the same year. But your where clause is taking care of that.

PostgreSQL using to_char for later batter aggregation, how to convert the Month part back to date

I am using the following to transfrom the date variable to YYYY and Mon
select
to_char(date, 'Mon') as month,
extract(year from date) as year,
v1,
count(v2) as count
from data
group by 1,2,3
order by 2,1;
However, when I do an order by, it does not order my data properly. So I think I have to convert Mon either to a number or back to a date to be able to sort it properly. Thoughts?
Of course not. It is ordering by the month name.
Instead, just order by the date:
order by date
If this were an aggregation query, then you would use an aggregation function:
order by min(date)
I would use a derived table where the grouping is done on a proper date value and convert it only for display purposes:
select to_char(month_date, 'Mon' as month,
extract(year from month_date) as year,
v1,
count
from (
select date_trunc('month', "date") as month_date
v1,
count(v2) as count
from data
group by 1,2
)
order by month_date

How to order months by name after having converted them from integers?

I'm learning Postgresql. I have this table with dates(DateTime type) and orders. My goal is to display the amount of orders done in a month, but I also need to show the names of the months in order.
I'm able to do the first part but I'm having trouble figuring out how to order the months, since I've already converted them from dates to strings. So this is what I've been doing:
SELECT TO_CHAR(created_at, 'Month') as month_name, COUNT(id) as orders
FROM orders
WHERE aasm_state != 'cart'
GROUP BY month_name
ORDER BY to_date(month_name, 'Month')
Then, I get "ERROR: column "month_name" does not exist".
I know the problem is in the last line because if I take it out I get no error.
Thanks in advance.
You could change to this. As for postgreSQL, you could use column alias in GROUP BY clause to "save" your typing, although for general it should not be supported.
SELECT TO_CHAR(created_at, 'Month') as month_name, COUNT(id) as orders
FROM orders
WHERE aasm_state != 'cart'
GROUP BY date_part('month', created_at), TO_CHAR(created_at, 'Month') --, month_name
ORDER BY date_part('month', created_at);
Or try this
SELECT TO_CHAR(created_at, 'Month') as month_name, COUNT(id) as orders
FROM orders
WHERE aasm_state != 'cart'
GROUP BY TO_CHAR(created_at, 'Month')
ORDER BY EXTRACT(MONTH FROM to_date(TO_CHAR(created_at, 'Month') || ' 2019', 'Month YYYY'));
Your order by can just use the column alias:
SELECT TO_CHAR(created_at, 'Month') as month_name, COUNT(id) as orders
FROM orders
WHERE aasm_state <> 'cart'
GROUP BY month_name
ORDER BY month_name;
The problem in your query is the expression on month_name. You would have still gotten a type-conversion error (I think) if the code ran.
So, month_name can be used in ORDER BY. However, it cannot be used in an expression.
The simplest way to order chronologically is:
order by min(created_at)

SQL Query to show all results before current month

I have a table in Oracle with columns: [DATEID date, COUNT_OF_PHOTOS int]
This table basically represents how many photos were uploaded per day.
I have a query that summarizes the number of photos uploaded per month:
select extract(year from dateid) as year, extract(month from dateid) as month, count(1) as Photos
from picture_table
group by extract(year from dateid), extract(month from dateid)
order by 1, 2
This does what I want, but I would like to run this query at the beginning of each month, lets say 07-02-2012, and have all data EXCLUDING the current month. How would I add a WHERE clause that ignores all entries that have a date equal to the current year+month?
Here is one way:
where to_char(dateid, 'YYYY-MM') <> to_char(sysdate, 'YYYY-MM')
To preserve any indexing strategy you may have on dateid:
select extract(year from dateid) as year, extract(month from dateid) as month, count(1) as Photos
from picture_table
WHERE (dateid < TRUNC(SYSDATE,'MM') OR dateid >= ADD_MONTHS(TRUNC(SYSDATE,'MM'),1))
group by extract(year from dateid), extract(month from dateid)
order by 1, 2