How to write a Report query based on number of days in a month? - sql

I am trying to write a query to generate automated report. This report is to run for last month's transactions it should run on 1st of every month. I have job to run this report to run 1st of every month. But how can I make this query to choose no of days in a month? (some months will have 30 and some will have 31 and in feb no of days changes based on leap year).
Here one more requirement is I only have to pass one parameter in the query. below is example of query that I have now
select id,name,address,trans_dt from tab1 where trans_dt between to_date('&1','MM-DD-YYYY')-30 AND to_date('&1','MM-DD-YYYY');
The above query is generating last 30 days transactions, but it will be wrong if no days for month is 31 or 28. I am using oracle 11r2 as database. Please help in writing this.

mySQL
SELECT
id,
NAME,
address,
trans_dt
FROM
tab1
WHERE
MONTH(trans_dt) = 02 /* Param for month passed in */
AND
YEAR(trans_dt) = YEAR(CURDATE())
Oracle
SELECT
id,
NAME,
address,
trans_dt
FROM
tab1
WHERE
to_char( dt_column, 'mm' ) = 02 /* Param for month passed in */
AND
EXTRACT(YEAR FROM DATE trans_dt) = trunc(sysdate, 'YEAR')
Maybe this can work? I only really know mySQL

Found solution but forget to reply here. Here is my solution
select id,name,address,trans_dt from tab1 where trans_dt between trunc(trunc(sysdate,'MM')-1,'MM') and trunc(sysdate,'MM');
above will give you report from 1st day of month to last day of month from calender.

select id
,name
,address
,trans_dt from tab1
where trans_dt between to_date(p_dt,'yyyy-mmm-dd') and add_months(to_date(p_dt,'yyyy-mmm-dd'))

Related

Compare date filed with month and year in Postgres

I have a date field in one of my tables and the column name is from_dt. Now I have to compare a month and year combination against this from_dt field and check whether the month has already passed. The current database function uses separate conditions for the month and the year, but this is wrong as it will compare month and year separately. The current code is like this
SELECT bill_rate, currency FROM table_name WHERE
emp_id = employee_id_param
AND EXTRACT(MONTH FROM from_dt) <= month_param
AND EXTRACT(YEAR FROM from_dt) <= year_param
Now the fromt_dt field has value 2021-10-11. If I give month_param as 01 and year_param as 2022, this condition will not work as the month 10 is greater than 1, which I have given. Basically, I need to check whether 01-2022 (Jan 2022) is greater than r equal to 2021-10-01(October 1st, 2021). It would be very much helpful if someone can shed some light here.
If you just want to check whether one date is >= then another:
# select '2022-01-01'::date >= '2021-10-11'::date;
?column?
----------
t
If you want to restrict to year/month then:
select date_trunc('month','2022-01-01'::date) >= date_trunc('month', '2021-10-11'::date);
?column?
----------
t
Where the date_trunc components are:
select date_trunc('month','2022-01-01'::date) ;
date_trunc
------------------------
2022-01-01 00:00:00-08
select date_trunc('month','2021-10-11'::date) ;
date_trunc
------------------------
2021-10-01 00:00:00-07
See Postgres date_trunc for more information.
Assuming the given year_param and month_param are integers you can use the make_date function to create the first of the year_month and date_trunc to get the first on the month from the table. Just compare those values. (See date functions) So:
select bill_rate, currency
from table_name
where emp_id = employee_id_param
and date_trunc('month',from_dt) =
make_date( year_param, month_param, 01);

How to get year, month and day from seconds in PostgreSql?

I'm trying to create three columns based on date in seconds format.
My user.updated_at = 1521533490
I would like to get year, month and day separately and put these formatted values to columns for example:
year -> 2018, month -> 11, day -> 23
Does someone know how can I do that in pgSQL?
I would like to get year, month and day separately and put these formated values to columns
Don't do that.
Use a single column of type date or timestamp, depending on your application. Not every combination of your three columns will be a valid date. But every value in a single column of type date will be a valid date.
If you need the parts of a date separately, use PostgreSQL's date/time functions.
Try this approche to get differents arguments, then you can do whatever you want:
SELECT to_timestamp(1521533490); //2018-03-20T08:11:30.000Z
SELECT to_char(to_timestamp(1521533490), 'HH'); // 08 Hour
SELECT to_char(to_timestamp(1521533490), 'MI'); // 11 Minutes
SELECT to_char(to_timestamp(1521533490), 'SS'); // 30 Seconds
SELECT to_char(to_timestamp(1521533490), 'DD'); // 20 Day
SELECT to_char(to_timestamp(1521533490), 'Mon'); // MAR Month
SELECT to_char(to_timestamp(1521533490), 'YYYY'); // 2018 Year
Use the EXTRACT function.
SELECT to_timestamp(updated_at) "Date",
EXTRACT(YEAR FROM (to_timestamp(updated_at))) "Year",
EXTRACT(MONTH FROM (to_timestamp(updated_at))) "Month",
EXTRACT(DAY FROM (to_timestamp(updated_at))) "Day"
FROM users
Output
Date Year Month Day
2018-03-20T08:11:30Z 2018 3 20
SQL Fiddle: http://sqlfiddle.com/#!15/afe0e/15/0
More information on the EXTRACT function.

use of week of year & subsquend in bigquery

I need to show distinct users per week. I have a date-visit column, and a user id, it is a big table with 1 billion rows.
I can change the date column from the CSVs to year,month, day columns. but how do I deduce the week from that in the query.
I can calculate the week from the CSV, but this is a big process step.
I also need to show how many distinct users visit day after day, looking for workaround as there is no date type.
any ideas?
To get the week of year number:
SELECT STRFTIME_UTC_USEC(TIMESTAMP('2015-5-19'), '%W')
20
If you have your date as a timestamp (i.e microseconds since the epoch) you can use the UTC_USEC_TO_DAY/UTC_USEC_TO_WEEK functions. Alternately, if you have an iso-formatted date string (e.g. "2012/03/13 19:00:06 -0700") you can call PARSE_UTC_USEC to turn the string into a timestamp and then use that to get the week or day.
To see an example, try:
SELECT LEFT((format_utc_usec(day)),10) as day, cnt
FROM (
SELECT day, count(*) as cnt
FROM (
SELECT UTC_USEC_TO_DAY(PARSE_UTC_USEC(created_at)) as day
FROM [publicdata:samples.github_timeline])
GROUP BY day
ORDER BY cnt DESC)
To show week, just change UTC_USEC_TO_DAY(...) to UTC_USEC_TO_WEEK(..., 0) (the 0 at the end is to indicate the week starts on Sunday). See the documentation for the above functions at https://developers.google.com/bigquery/docs/query-reference for more information.

Sql daily comparison by month

I am writing a report for work which requires that I compare the amount of students dropped on a daily basis, what I mean is the report needs to show that on today the 5th of august X amounts of students dropped from the 1st to the 5th compared to X amount which dropped within the 1st to the 5th of July and so on for each Month of the year. Can anyone please help me by providing me with a query which I can use to have that info? thanks.
You want to compare the first number of days from a month. The following query gives you an example:
select yr, mon, count(*)
from (select extract(year from date) as yr, extract(month from date) as mon,
extract(day from date) as day
from t
) t
where day <= extract(day from now())
group by yr, mon
However, the exact syntax may depend on your database. For instance, the current date may be now(), getdate(), system_date or something else. Some databases don't support the extract, but most have a way to get the month and day of month.

Add date without exceeding a month

I hope someone could help me on this.
I want to add a month to a database date, but I want to prevent two jumping over month on those days at the end.
For instance I may have:
Jan 31 2009
And I want to get
Feb 28 2009
and not
March 2 2009
Next date would be
March 28 2009
Jun 28 2009
etc.
Is there a function that already perform this kind of operation in oracle?
EDIT
Yeap. I want to copy each month all the records with some status to the next ( so the user don't have to enter again 2,000 rows each month )
I can fetch all the records and update the date manually ( well in an imperative way ) but I would rather let the SQL do the job.
Something like:
insert into the_table
select f1,f2,f3, f_date + 30 /* sort of ... :S */ from the_Table where date > ?
But the problem comes with the last day.
Any idea before I have to code something like this?
for each record in
createObject( record )
object.date + date blabala
if( date > 29 and if februrary and the moon and the stars etc etc 9
end
update.... et
EDIT:2
Add months did the trick.
now I just have this:
insert into my_table
select f1, add_months( f2, 1 ) from my_table where status = etc etc
Thanks for the help.
Oracle has a built-in function ADD_MONTHS that does exactly that:
SQL> select add_months(date '2008-01-31',1) from dual;
ADD_MONTHS(
-----------
29-FEB-2008
SQL> select add_months(date '2008-02-29',1) from dual;
ADD_MONTHS(
-----------
31-MAR-2008
I think you're looking for LAST_DAY:
http://download.oracle.com/docs/cd/B28359_01/olap.111/b28126/dml_functions_2006.htm
I just did:
select add_months(TO_DATE('30-DEC-08'), 2) from dual
and got
28-FEB-2009
No need to use LAST_DAY. If you went that route, you could create a function that:
1. takes a date
2. Changes the day to the first of the month.
3. Add a month.
4. Changes the day to the LAST_DAY for that month.
I think you'll have to write it on your own, My advice is first to evaluate the "last day of the month" with this method:
Add one month (not 30 days, one month!)
Find first day of the month (should be easy)
substract one day
Then compare it to your "plus x days" value, and choose the lowest one (I understood the logic behind the jump from 31/Jan to 28/Feb, but I don't get it for the jump from 28-Feb to 28-Mar)
It sounds like you want the current month plus one (with appropriate rollover in December)
and the minimum of the last day of that month and the current day.