SQL Monthname Display in Query - sql

I am new to SQL and currently going through some training materials.
I need to: Display the month and number of quotations received in each month.
My Query
SELECT Qdate AS MONTH ,COUNT (Quotationid)AS QUOTATIONCOUNT
FROM Quotation
GROUP BY Qdate
ORDER BY Qdate ASC;
DB Structure
Quotation (Quotationid, Sname, Itemcode, Quotedprice, Qdate, Qstatus)

You are almost correct.
Below query for Oracle.
SELECT to_char(Qdate, 'MONTH') AS "MONTH" ,COUNT (Quotationid)AS QUOTATIONCOUNT
FROM Quotation
GROUP BY to_char(Qdate, 'MONTH')
ORDER BY "MONTH";

And to show month name:
in SQL Server, you can use DATENAME function in combination with DATEADD function. #MonthNum is your number of month, that means you can use: SELECT DateName(month, DateAdd(month, #MonthNum, 0) - 1)
in MySQL, you can use: MONTHNAME(date)

You need to extract the month and year to get what you want. Date/time functions are notoriously database-dependent. In standard SQL you can do:
SELECT EXTRACT(YEAR FROM Qdate) AS YYYY,
EXTRACT(MONTH FROM Qdate) AS MM,
COUNT(*) AS QUOTATIONCOUNT
FROM Quotation
GROUP BY EXTRACT(YEAR FROM Qdate), EXTRACT(MONTH FROM Qdate)
ORDER BY MIN(Qdate) ASC;
The specific functions you want depend on the database you are using.
Important points:
You should not be considering the month without the year, unless you have a really good reason.
In general, you need to repeat the expressions in the GROUP BY, although some databases do allow column aliases (such as GROUP BY YYYY, MM in the above example).
The ORDER BY needs to use an expression that only consists of expressions in the GROUP BY or aggregation functions (so ORDER BY QDate wouldn't work).

Related

Column alias is not recognized [duplicate]

This question already has answers here:
Referring to a select aggregate column alias in the having clause in Postgres
(2 answers)
Closed 2 years ago.
This minimal example is supposed to extract year from time stamps, then count something in a given year.
SELECT EXTRACT(YEAR FROM rental_ts) as year,
COUNT(DISTINCT rental_id)
FROM rental
GROUP BY year
HAVING year=2020
Running it, I get an error column "year" does not exist. What is the reason for this?
Code with explicit HAVING EXTRACT(YEAR FROM rental_ts)=2020 works without problems, but not very convenient.
Same would happen if I use year in WHERE clause instead.
I practice in this playground. It uses PostgreSQL.
Alas, that is true. Column aliases are not allowed. One solution is to repeat the expression:
SELECT EXTRACT(YEAR FROM rental_ts) as year,
COUNT(DISTINCT rental_id)
FROM rental
GROUP BY year
HAVING EXTRACT(YEAR FROM rental_ts) = 2020;
A better solution is to filter before aggregating:
SELECT EXTRACT(YEAR FROM rental_ts) as year,
COUNT(DISTINCT rental_id)
FROM rental
WHERE rental_ts >= '2020-01-01' AND rental_ts < '2021-01-01'
GROUP BY year;
This is better for two reasons. First, it is index (and partition) compatible. Second, it reduces the amount of data needed for the aggregation.

Display By month using select statement

SELECT SUM(Total_A ) FROM Materials_List
This is the snippet of code that I have.
I need it to calculate by month and display by month using SQL.
I also would like it to be a code I can use for any month in the year not just one month at a time.
You seem to be looking for simple aggregation:
select
year(materials_datetime) yr,
month(materials_datetime) mn,
sum(total_a) sum_total_a
from materials_list
group by
year(materials_datetime),
month(materials_datetime)
order by yr, mn
This assumes that column materials_datetime contains the date/time that you want to use to aggregate the data.

Oracle query displays data by month and year

I want to display the amount of data by month and year. This is an example of displaying data by date:
select count(*) from db.trx where trxdate = to_date('2018-04-23','yyyy-mm-dd')
When I try to display the amount of data by month and year, no query results appear. Is there something wrong with the query?
The query:
select count(*) from db.trx where trxdate = to_date('2018-04','yyyy-mm')
You need to apply the function to trxdate. Using your logic:
SELECT Count(*)
FROM olap.trxh2hpdam
WHERE To_char(trxdate, 'YYYY-MM') = '2018-04';
However, I strongly recommend that you use direct date comparisons:
WHERE trxdate >= date '2018-04-01'
AND
trxdate < date '2018-05-01'
This will allow the database to use an index on trxdate.
There are a couple of ways of accomplishing what you're trying to do. Which one works for you will depend on your database design (for example, the indexes you've created). One way might be this:
SELECT COUNT(*) FROM olap.trxh2hpdam
WHERE TRUNC(trxdate, 'MONTH') = DATE'2018-04-01';
This will round the date down to the first of the month (and, of course, remove any time portion). Then you simply compare it to the first of the month for which you want the data. However, unless you have an index on TRUNC(trxdate, 'MONTH'), this may not be the best course of action; if trxdate is indexed, you'll want to use:
SELECT COUNT(*) FROM olap.trxh2hpdam
WHERE trxdate >= DATE'2018-04-01'
AND trxdate < DATE'2018-05-01';
There are a number of functions at your disposal in Oracle (e.g. ADD_MONTHS()) in the event that the date you use in your query is supposed to be dynamic rather than static.
Just FYI, there is no reason not to use ANSI date literals when trying to retrieve data by day as well. I'm not sure your original query is a good example of getting data for a particular day, since the Oracle DATE datatype does at least potentially include a time:
SELECT COUNT(*) FROM olap.trxh2hpdam
WHERE trxdate >= DATE'2018-04-23'
AND trxdate < DATE'2018-04-24';
or:
SELECT COUNT(*) FROM olap.trxh2hpdam
WHERE TRUNC(trxdate) = DATE'2018-04-23';
EDIT
In case the month and year are dynamic, I would build a date from them (e.g., TO_DATE('<year>-<month>-01', 'YYYY-MM-DD')) and then use the following query:
SELECT COUNT(*) FROM olap.trxh2hpdam
WHERE trxdate >= TO_DATE('<year>-<month>-01', 'YYYY-MM-DD')
AND trxdate < ADD_MONTHS( TO_DATE('<year>-<month>-01', 'YYYY-MM-DD'), 1 );
Hope this helps.

Aggregate on relative daterange in Oracle SQL

I have a table with several columns I would like to aggregate on, I have already aggregated on absolute days, but now I want to aggregate relatively. In my table I have a timestamp, and I would like to group by a date range so that the datestamp's day is 0, the day after 1 and so forth.
SELECT count(*) num_elements, sum(some_value) like_to_sum, reldate
FROM the_large_table
GROUP BY *** what goes here *** reldate.
Can I aggregate on the return from a function, or is there a better way to approach this problem.
If I can aggregate on the result from a function, are there any functions for this already in SQL, or how could this be solved?
SELECT
COUNT(*) AS num_elements,
SUM(some_value) AS like_to_sum,
TRUNC(SYSDATE) - TRUNC(your_date) AS rel_date
FROM the_large_table
GROUP BY TRUNC(SYSDATE) - TRUNC(your_date);

Oracle date / order by question

I want to select a date from oracle table formatted like select (to_char(req_date,'MM/YYYY')) but I also want to order the result set on this date format.
I want them to be ordered like dates not strings.
Like this
09/2009
10/2009
11/2009
12/2009
01/2010
02/2010
03/2010
04/2010
05/2010
06/2010
07/2010
08/2010
09/2010
10/2010
11/2010
12/2010
Not like
01/2010
02/2010
03/2010
04/2010
05/2010
06/2010
07/2010
08/2010
09/2009
09/2010
10/2009
10/2010
11/2009
11/2010
12/2009
12/2010
Any way to do this in sql?
Full SQL is:
SELECT (to_char(req_date,'MM/YYYY')) as monthYear, count(req_id) as count
FROM REQUISITION_CURRENT t
GROUP BY to_char(req_date,'MM/YYYY')
Thanks
Try this. It works and it's efficient, but looks a little messy.
select to_char(trunc(req_date, 'MM'),'MM/YYYY') as monthYear
,count(req_id) as count
from requisition_current
group
by trunc(req_date, 'MM')
order
by trunc(req_date, 'MM');
Try this
select monthyear,yr,month,count(req_id)
from
(
SELECT (to_char(req_date,'MM/YYYY')) as monthYear, to_char(req_date,'YYYY') yr, to_char(req_date,'mm') month, req_id
FROM REQUISITION_CURRENT t
) x
GROUP BY monthyear,yr,month
order by yr, month
Please try
Select req_date, (to_char(req_date,'MM/YYYY')) from MY_TABLE order by req_date
You are free to add additional sort fields, even if they are the same field.
Just use order by req_date instead of order by to_char(req_date,'MM/YYYY').
Try
SELECT ...
ORDER BY MIN(req_date)
That'll get around Oracle's rules about what can be selected after a GROUP BY.
I am considerably late to the party, but the most intuitive way I've found to achieve this is the following:
SELECT DISTINCT
to_char(req_date,'MM/YYYY') as monthYear,
count(req_id) as count
FROM
REQUISITION_CURRENT t
GROUP BY
to_char(req_date,'MM/YYYY')
ORDER BY
to_date(monthYear,'MM/YYYY')
It's may not the most computationally efficient method since it converts the date to a character and then back to a date, but that is precisely what you are asking a query like this to do. It also saves you from adding support columns or nesting subqueries.