Oracle SQL : Expand year to a full date - oracle10g

This must be simple to answer, but how do you expand in Oracle a year to a full date, e.g.
1996 to 1996-01-01 00:00:00 ?
EDIT
The data type of the year is char, and I want to end up by comparing this year to a string-date, e.g.
1996 <= '1998-31-12 12:04:35'
It is important that the expanded data is expanded in the same data Format (since I get the dates preformatted)
At the end I need something like this
WHERE ( to_date(table.year_char ,'YYYY') <= '1996-12-31 00:00:00')
or sth like this
WHERE ( to_char(to_date(table.year_char ,'YYYY')) <= '1996-12-31 00:00:00')
or anything which works

If you're starting with the year as a string and you want to end up with a DATE object, you use the TO_DATE() function; but you need to supply a dummy month or it'll default to the first day of the current month in the specified year:
select to_date('1996', 'YYYY') from dual;
May, 01 1996 00:00:00+0000
SQL Fiddle
With the month, and to make it clearer the day too, appended and a suitable format model:
select to_date('1996' ||'-01-01', 'YYYY-MM-DD') from dual
January, 01 1996 00:00:00+0000
SQL Fiddle. I've left the year and the '-01-01' literal separate and concatenated on the assumption that you'll be using a variable really...
In a WHERE clause, using the sample date you initially showed:
select * from dual
where to_date('1996' ||'-01-01', 'YYYY-MM-DD')
<= to_date('1998-31-12 12:04:35', 'YYYY-DD-MM HH24:MI:SS')
Or if you're actually comparing to a string as your second example suggests, just leave it as a string, as you want both sides of the comparison to be the same data type without any implicit conversion that might cause you problems later. The string you have fortunately has the data in a format that is comparable:
WHERE (table.year_char || '-01-01 00:00:00' <= '1996-12-31 00:00:00')
You could convert it to and back from a DATE but there isn't any benefit in doing so.

Related

How to extract Year and Month in SQL Postgres by using Data_Part function

I am facing an issue extracting the month and year from the data (in Character varying type) >> InvoiceDate in SQL Postgres. I have seen the solution is relatively easy with MySQL function: DATEFROMPARTS as per the below Code which is not available in SQLpostgres. How can I get the same result DATA_PART function in Postgres SQL, but simultaneously I need to change the data type of the column "InvoiceDate" to the date
Select
CustomerID,
min(InvoiceDate) first_purchase_date,
DATEFROMPARTS(year(min(InvoiceDate)), month(min(InvoiceDate)), 1) Cohort_Date
into #cohort
from #online_retail_main
group by CustomerID
The output:
Customer ID| first_purchase_date |Cohort_Date|
-----------+-------------------------+-----------+
12345 | 2010-12-20 15:47:00:00 | 2010-12-01|
I am trying to make a date consits of Year and Month , while the day to be set as 1 for all
Assuming a valid Postgres timestamp:
select date_trunc('month', '2010-12-20 15:47:00.00'::timestamp)::date;
date_trunc
------------
12/01/2010
--or ISO format
set datestyle = 'ISO,MDY';
select date_trunc('month', '2010-12-20 15:47:00.00'::timestamp)::date;
date_trunc
------------
2010-12-01
Uses date_trunc to truncate the timestamp to a month which means the first of the month. Then cast(::date) to a date type. The DateStyle just deals with how the value is presented to the user. The value is not stored formatted.
To do something similar to what you did in MySQL:
select make_date(extract(year from '2010-12-20 15:47:00.00'::timestamp)::integer, extract(month from '2010-12-20 15:47:00.00'::timestamp)::integer, 1);
This uses make_date from here Date/time functions and extract to build a date.

How to store mmyy in Postgres?

There are two variables:
$mm = "01";
$yy = "22";
I need to store it in one column Postges mmyy.
What is type mmyy must be if there is not day?
Or I can use the first day of month always like: 010122.
Eventually, I want to filter rows with where mmyy > now().
If you want to treat it like a date/time value, preferably store it as date. That would be:
date '2022-01-01'
Occupies only 4 bytes, same as int4.
Always use ISO format, which is unambiguous regardless of your locale settings. More in the manual.
To convert your variables, you might use the Postgres function to_date():
test=> SELECT to_date('2201', 'YYMM');
to_date
------------
2022-01-01
(1 row)
test=> SELECT to_date('22'::text || '01'::text, 'YYMM');
to_date
------------
2022-01-01
(1 row)
Or prepare a date literal in ISO format.
When compared to now() (which returns timestamp with time zone) the date value is coerced to the first instant of Jan 1st, 2022 at the time zone determined by the current setting of your session. See:
Difference between now() and current_timestamp
So it works as intended out of the box - except that you possibly haven't thought about time zones, yet ...
For other tasks with date arithmetic, an integer might be a good choice. See:
How do you do date math that ignores the year?

Datediff function in T-sql

What will be the output the following call:
DATEDIFF(wk,14,GET DATE())
14 indicates a date or it indicates 2 weeks difference?
from here https://learn.microsoft.com/en-us/sql/t-sql/functions/datediff-transact-sql?view=sql-server-2017
DATEDIFF ( datepart , startdate , enddate )
so 14 should indicate start date. Check example, because adding just 14 doesn't make sense, it should be a date, e.g.
SELECT DATEDIFF(week, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
As svkaka wrote in his answer, the DATEDIFF function expects a datepart, start date and end date - However, your code supplies it with an int as it's second argument.
In such cases, SQL Server will implicitly convert the int to DateTime, so
SELECT DATEDIFF(wk, 14, GetDate())
is in fact
SELECT DATEDIFF(wk, '1900-01-15', GetDate())
Since casting 14 to DateTime will result with that date.
Please note, however, that none of the other Date/Time data types can be directly converted from an int.
This is the basis of a technique that was used in older versions of SQL Server to truncate parts of a DateTime value.
For instance, if you wanted to truncate the time part in 2005 version, you would do this:
SELECT DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0) -- 0 meaning January 1st 1900
(in 2008 you would simply cast to date).
However, in the newer versions of SQL Server (in fact, since 2012 introduced datefromparts and it's sibling functions) this technique is no longer needed.

Getting a weird result for ISO Date in Postgresql

I have a table task_details. I need to select its weekly date from this table. I have used ISO Year & ISO Week to extract the weekly dates from this table as I want to extract its week number as 53 if its Dec,2015 then on the days 28 Dec,29 Dec,30 Dec,31 Dec and 1 Jan '16,2 Jan '16 since it should not separate to two different weeks for these sort of dates. The query I have used for ISO Year & ISO Week is given below.
select
name, id,
to_date(week || ' ' || yr, 'IW IYYY') week_date,
sum(worked_hours) worked_hours_per_week,
week, yr
from (
select
name, id,
newdate, hours worked_hours,
to_number(to_char(newdate, 'IW'), '99') week,
extract( year from newdate) yr
from task_details t
) sub
where worked_hours > 0
group by name, id, to_date(week || ' ' || yr, 'IW IYYY'), week, yr
order by yr, week
It is working fine for the weeks but then I am getting this weird result for one date for a record in the table. The table doesn't have the data for the year 2017.Also, the yr column is showing 2016 which is as desired but then the newdate column and week column is giving weird result. Why is this happening? How do I fix this ?
Here is the SQL fiddle for it :http://sqlfiddle.com/#!15/53abf/1
You should not mix week with year in the extract function as year is for the Gregorian calendar rather than the special ISO calendar.
See section 9.9.1 and comments about week.
to_number(to_char(newdate, 'IW'), '99') is effectively extract(week from newdate)
Changing the yr column to be extract(isoyear from newdate) solves your problem.
Adjusted SQL Fiddle
#gwaigh already cleared up your confusion of Gregorian and ISO year.
However, your query would be simpler and faster with date_trunc() to get the first day of each week:
SELECT name, id
, date_trunc('week', newdate)::date AS week_date
, extract(week FROM newdate)::int AS week
, extract(isoyear from newdate)::int AS isoyr -- must be ISO year to match
, sum(hours) AS worked_hours_per_week
FROM task_details
WHERE hours > 0
GROUP BY name, id, week_date, week, yr
ORDER BY week_date;
Also simplified your query.
SQL Fiddle.
Either way, if you work with timestamptz then year, week or date depend on your current timezone setting. (It can be a different year, depending on where you are right now.)

ORA-01843: not a valid month - but what month format? Oracle 11g

I want to know what other MONTH formats exist except MM , MONTH or MON.
When the query below runs it gives me an error ORA-01843: not a valid month and I can understand why, because the server removes the "0" from the month "07" and leaves only the number "7", so the MM format is not the right one.
But which one is it?
select to_char(to_date(START_DATE,'MM/DD/YYYY '), 'DD-MM-YYYY')
from PER_ALL_PEOPLE_F
WHERE person_id=12345
The START_DATE column is DATE TYPE and it provides results like: 7/17/2012 .
Your assumption that the single-digit 7 for the month is a problem is not correct; Oracle is generally quite flexible and will happily parse a single digit month with the MM model:
select to_date('7/17/2012', 'MM/DD/YYYY') from dual;
TO_DATE('7/17/2012'
-------------------
2012-07-17 00:00:00
If start_date is already a DATE type then you should not be calling to_date() for it. You're doing an implicit conversion to a string using your NLS_DATE_FORMAT moodel, and then back to a date with your specified format. So really you're doing:
select to_char(to_date(to_char(START_DATE, <NLS_DATE_FORMAT>),
'MM/DD/YYYY '), 'DD-MM-YYYY')
If your NLS_DATE_FORMAT is something other than MM/DD/YYYY, e.g. DD-MON-YYYY, then you'll get an ORA-1843 error for at least some values.
You can see this with:
select to_date(date '2014-01-16', 'MM/DD/YYYY') from dual;
or the expanded:
select to_date(to_char(date '2014-01-16', 'DD-MON-YYYY'),
'MM/DD/YYYY') from dual;
Dates do not have any specific format, they're stored in an internal representation and then converted to a formatted string for display. You said your dates display like 7/12/2012, but given the error you're seeing your client seems to be doign that formatting, and it isn't related to the session NLS_DATE_FORMAT.
You only need to do:
select to_char(START_DATE, 'DD-MM-YYYY')