DB2 SQL extract only month and year from date column - sql

I trying to group by month and year from MGMOV00F table - date column is DTMOMM, trying the syntax below but still getting error: argument 1 of function year not valid, anybody help please ?

Are you sure your dealing with an actual date data type?
Given the WHERE DT01MM > '20160101'
It would appear to me you're dealing with character columns; since AFAIK DB2 won't implicitly cast '20160101' to date like it would '2016-01-01'.
That being the case, your task is easy. Simply substring the first 6 characters..

Selects count of month-year (m-yyyy) ordered by number of matches:
SELECT valid_from, COUNT(1) FROM (
SELECT (
EXTRACT(MONTH FROM valid_from)
CONCAT '-' CONCAT
EXTRACT(YEAR FROM valid_from)
) AS valid_from
FROM some_table NOLOCK
) as s
GROUP BY s.valid_from
ORDER BY 2 DESC;
Result:

Related

SQL No of count month wise

I have a data set as below,
data is basically year and month YYYYMM, I need to bring a count of months eg 202001 is appearing 3 times, hence the count should be Nov 3 ( Desired output is shared below )
I'm unable to start to bring out the desired output, help would be much appreciated.
(Temp tables are not allowed to be created in the servers)
Please find the link for sample data link
Help would be much appretiated.
You can use to_date() to convert your number to a proper date, then group by that date:
select to_date(due_date_key::text, 'yyyymm') as due_date,
count(*)
from t
group by due_date;
The "due_date" column is a proper date, you can use the to_char() function to format it differently:
select to_char(due_date, 'yyyy') as year,
to_char(due_date, 'Mon') as output,
count
from (
select to_date(due_date_key::text, 'yyyymm') as due_date,
count(*)
from t
group by due_date
) t
order by due_date;
Online example

Athena greater than condition in date column

I have the following query that I am trying to run on Athena.
SELECT observation_date, COUNT(*) AS count
FROM db.table_name
WHERE observation_date > '2017-12-31'
GROUP BY observation_date
However it is producing this error:
SYNTAX_ERROR: line 3:24: '>' cannot be applied to date, varchar(10)
This seems odd to me. Is there an error in my query or is Athena not able to handle greater than operators on date columns?
Thanks!
You need to use a cast to format the date correctly before making this comparison. Try the following:
SELECT observation_date, COUNT(*) AS count
FROM db.table_name
WHERE observation_date > CAST('2017-12-31' AS DATE)
GROUP BY observation_date
Check it out in Fiddler: SQL Fidle
UPDATE 17/07/2019
In order to reflect comments
SELECT observation_date, COUNT(*) AS count
FROM db.table_name
WHERE observation_date > DATE('2017-12-31')
GROUP BY observation_date
You can also use the date function which is a convenient alias for CAST(x AS date):
SELECT *
FROM date_data
WHERE trading_date >= DATE('2018-07-06');
select * from my_schema.my_table_name where date_column = cast('2017-03-29' as DATE) limit 5
I just want to add my little words here, if you have date column with ISO-8601 format, for example: 2022-08-02T01:46:46.963120Z then you can use parse_datetime function.
In my case, the query looks like this:
SELECT * FROM internal_alb_logs
WHERE elb_status_code >= 500 AND parse_datetime(time,'yyyy-MM-dd''T''HH:mm:ss.SSSSSS''Z') > parse_datetime('2022-08-01-23:00:00','yyyy-MM-dd-HH:mm:ss')
ORDER BY time DESC
See more other examples here: https://docs.aws.amazon.com/athena/latest/ug/application-load-balancer-logs.html#query-alb-logs-examples

SQL query for multiple values of a column

I have db with names etc with date of birth. How can I get count of columns for all 12 months of the dates?
Exact code depends on the database you use; you should, somehow, "extract" month from date of birth in order to GROUP BY it.
In Oracle, you might have done it as
select to_char(date_of_birth), 'mon') dob_month,
count(*)
from your_table
group by to_char(date_of_birth, 'mon');
or
select extract(month from date_of_birth) dob_month,
count(*)
from your_table
group by extract(month from date_of_birth);

Query to Find First and Last Day of Current Month excluding sunday in sql

i need to get the data of monthly report which should exclude Sunday in all the weeks...where am not able to exclude Sunday. Kindly check the below query:
select Name,Actual_Hours,round((Actual_Hours/((DATEDIFF(DAY,'12-01-2016' ,'12-14-2016')+1)*8.5))*100,0)as percentage
from (select Name , SUM(actual_Hours) Actual_Hours
from ( select Name,ACTUAL_HOURS=sum(DATEPART(hh,[Time_Taken_in_Min]))+sum(DATEPART(MINUTE,[Time_Taken_in_Min])) /60
FROM [HR_Admin].[dbo].[Mst_Daily_Report_Pds] where date between '12-01-2016' and '12-14-2016' and (DATENAME(weekday,Date)) not in ('sunday')
GROUP BY Name )o group by Name )a order by Actual_Hours desc
Don't know exactly what error you are getting but I don't see the issue in SQL, but I believe it's because of the use of DATEDIFF in the select query instead of using the actual days.
Check the below query which uses the actual days (already removed Sunday in Where clause) and using less subquery. You can further improve this by taking only the time factor in the innermost query and then rounding off after summing all the hours.
Another suggestion is to avoid using the column name as reserved word like Date as it could create confusion, or using the column in Square brackets like [Date].
select Name
, sum(Actual_Hours) as Actual_Hours
, round((sum(Actual_Hours)/COUNT([Day])*8.5)*100,0) as percentage
from (select Name
, DATEPART(DAYOFYEAR,[Date]) as [Day]
, ACTUAL_HOURS=sum(sum(DATEPART(hh,[Time_Taken_in_Min]))+sum(DATEPART(MINUTE,[Time_Taken_in_Min])) /60)
FROM [HR_Admin].[dbo].[Mst_Daily_Report_Pds]
where date between '12-01-2016' and '12-14-2016'
and (DATENAME(weekday,[Date])) not in ('Sunday')
GROUP BY Name, [Date]
) a
GROUP BY Name
order by Actual_Hours desc

Last day of the month with a twist in SQLPLUS

I would appreciate a little expert help please.
in an SQL SELECT statement I am trying to get the last day with data per month for the last year.
Example, I am easily able to get the last day of each month and join that to my data table, but the problem is, if the last day of the month does not have data, then there is no returned data. What I need is for the SELECT to return the last day with data for the month.
This is probably easy to do, but to be honest, my brain fart is starting to hurt.
I've attached the select below that works for returning the data for only the last day of the month for the last 12 months.
Thanks in advance for your help!
SELECT fd.cust_id,fd.server_name,fd.instance_name,
TRUNC(fd.coll_date) AS coll_date,fd.column_name
FROM super_table fd,
(SELECT TRUNC(daterange,'MM')-1 first_of_month
FROM (
select TRUNC(sysdate-365,'MM') + level as DateRange
from dual
connect by level<=365)
GROUP BY TRUNC(daterange,'MM')) fom
WHERE fd.cust_id = :CUST_ID
AND fd.coll_date > SYSDATE-400
AND TRUNC(fd.coll_date) = fom.first_of_month
GROUP BY fd.cust_id,fd.server_name,fd.instance_name,
TRUNC(fd.coll_date),fd.column_name
ORDER BY fd.server_name,fd.instance_name,TRUNC(fd.coll_date)
You probably need to group your data so that each month's data is in the group, and then within the group select the maximum date present. The sub-query might be:
SELECT MAX(coll_date) AS last_day_of_month
FROM Super_Table AS fd
GROUP BY YEAR(coll_date) * 100 + MONTH(coll_date);
This presumes that the functions YEAR() and MONTH() exist to extract the year and month from a date as an integer value. Clearly, this doesn't constrain the range of dates - you can do that, too. If you don't have the functions in Oracle, then you do some sort of manipulation to get the equivalent result.
Using information from Rhose (thanks):
SELECT MAX(coll_date) AS last_day_of_month
FROM Super_Table AS fd
GROUP BY TO_CHAR(coll_date, 'YYYYMM');
This achieves the same net result, putting all dates from the same calendar month into a group and then determining the maximum value present within that group.
Here's another approach, if ANSI row_number() is supported:
with RevDayRanked(itemDate,rn) as (
select
cast(coll_date as date),
row_number() over (
partition by datediff(month,coll_date,'2000-01-01') -- rewrite datediff as needed for your platform
order by coll_date desc
)
from super_table
)
select itemDate
from RevDayRanked
where rn = 1;
Rows numbered 1 will be nondeterministically chosen among rows on the last active date of the month, so you don't need distinct. If you want information out of the table for all rows on these dates, use rank() over days instead of row_number() over coll_date values, so a value of 1 appears for any row on the last active date of the month, and select the additional columns you need:
with RevDayRanked(cust_id, server_name, coll_date, rk) as (
select
cust_id, server_name, coll_date,
rank() over (
partition by datediff(month,coll_date,'2000-01-01')
order by cast(coll_date as date) desc
)
from super_table
)
select cust_id, server_name, coll_date
from RevDayRanked
where rk = 1;
If row_number() and rank() aren't supported, another approach is this (for the second query above). Select all rows from your table for which there's no row in the table from a later day in the same month.
select
cust_id, server_name, coll_date
from super_table as ST1
where not exists (
select *
from super_table as ST2
where datediff(month,ST1.coll_date,ST2.coll_date) = 0
and cast(ST2.coll_date as date) > cast(ST1.coll_date as date)
)
If you have to do this kind of thing a lot, see if you can create an index over computed columns that hold cast(coll_date as date) and a month indicator like datediff(month,'2001-01-01',coll_date). That'll make more of the predicates SARGs.
Putting the above pieces together, would something like this work for you?
SELECT fd.cust_id,
fd.server_name,
fd.instance_name,
TRUNC(fd.coll_date) AS coll_date,
fd.column_name
FROM super_table fd,
WHERE fd.cust_id = :CUST_ID
AND TRUNC(fd.coll_date) IN (
SELECT MAX(TRUNC(coll_date))
FROM super_table
WHERE coll_date > SYSDATE - 400
AND cust_id = :CUST_ID
GROUP BY TO_CHAR(coll_date,'YYYYMM')
)
GROUP BY fd.cust_id,fd.server_name,fd.instance_name,TRUNC(fd.coll_date),fd.column_name
ORDER BY fd.server_name,fd.instance_name,TRUNC(fd.coll_date)