Problem when extracting year and week number from string in PSQL - postgresql

Let's say that I have a range of SQL tables that are named name_YYYY_WW where YYYY = year and WW = week number. If I call upon a function that guides a user defined date to the right table.
If the date entered is "20110101":
SELECT EXTRACT (WEEK FROM DATE '20110101') returns 52 and
SELECT EXTRACT (YEAR FROM DATE '20110101') returns 2011.
While is nothing wrong with these results I want "20110101" to either point to table name_2010_52 or name_2011_01, not name_2011_52 as it does now when I concanate the results to form the query for the table.
Any elegant solutions to this problem?

The function to_char() will allow you to format a date or timestamp to output correct the iso week and iso year.
SELECT to_char('2011-01-01'::date, 'IYYY_IW') as iso_year_week;
will produce:
iso_year_week
---------------
2010_52
(1 row)

You could use a CASE:
WITH sub(field) AS (
SELECT CAST('20110101' AS date) -- just to test
)
SELECT
CASE
WHEN EXTRACT (WEEK FROM field ) > 1 AND EXTRACT (MONTH FROM field) = 1 AND EXTRACT (DAY FROM field) < 3 THEN 1
ELSE
EXTRACT (WEEK FROM field)
END
FROM
sub;

Related

Number of days in a month in DB2

Is there a way to find the number of days in a month in DB2. For example I have a datetime field which I display as Jan-2020, Feb-2020 and so on. Based on this field I need to fetch the number of days for that month. The output should be something like below table,
I'm using the below query
select reportdate, TO_CHAR(reportdate, 'Mon-YYYY') as textmonth from mytable
Expected output
ReportDate textMonth No of Days
1-1-2020 08:00 Jan-2020 31
1-2-2020 09:00 Feb-2020 29
12-03-2020 07:00 Mar-2020 31
Try this:
/*
WITH MYTABLE (reportdate) AS
(
VALUES
TIMESTAMP('2020-01-01 08:00:00')
, TIMESTAMP('2020-02-01 09:00:00')
, TIMESTAMP('2020-03-12 07:00:00')
)
*/
SELECT reportdate, textMonth, DAYS(D + 1 MONTH) - DAYS(D) AS NO_OF_DAYS
FROM
(
SELECT
reportdate, TO_CHAR(reportdate, 'Mon-YYYY') textMonth
, DATE(TO_DATE('01-' || TO_CHAR(reportdate, 'Mon-YYYY'), 'dd-Mon-yyyy')) D
FROM MYTABLE
);
Db2 has the function DAYS_TO_END_OF_MONTH and several others which you could use. Based on your month input, construct the first day of the month. This should be something like 2020-01-01 for Jan-2020 or 2020-02-01 for Feb-2020. Follow the link for several other conversion functions which allow you to transform between formats and to perform date arithmetics.
convert your column to a proper date and try this: day(last_day(date_column))

Extract Only Date from timestamp in postgres

I have a 'timestamp without time zone' value in a column example:
PunchIn = "2019-06-10 09:10:00"
How can I extract "2019-06-10 00:00:00" from this column?
demo:db<>fiddle
SELECT my_date::date::timestamp
This converts the date column my_date to date (cuts the time part) and if you cast it back into timestamp it gets the 0 time.
Alternatively you can use the date_trunc function:
SELECT date_trunc('day', my_date)
SELECT SUBSTRING("PunchIn = '2019-06-10 09:10:00'" FROM 11 FOR 21);
should return the string you're looking for (if I count the index number right:)
You can use the DATE function to extract date:
SELECT DATE(SUBSTRING("PunchIn = '2019-06-10 09:10:00'" FROM 11 FOR 21));

Comparing date values for two columns

I have a column called PairDt, a string that contains a date value in the last 5 characters. I want to compare that date value with the date value in the Day column, which contains dates in the YYYY-MM-DD format.
PairDt Day
----------------------------------
DCS-CNY-Yunbi-42606 2016-08-24
DCS-CNY-Yunbi-42607 2016-08-25
DCS-CNY-Yunbi-42608 2016-08-26
DCS-CNY-Yunbi-42609 2016-08-27
DCS-CNY-Yunbi-42610 2016-08-28
How do I convert Day to a value?
I'm trying to isolate Date values in PairDt that does not match the date value in Days
This 5 digit number at the end of PairDt looks like number of days since December 30th 1899. To convert this number to date use DATEADD to add as many days. To convert a date to number, use DATEDIFF to calculate the number of days. Something like this code:
declare #PairDt varchar(50) = 'DCS-CNY-Yunbi-42606', #Day date = '2016-08-24'
select DATEADD(d, cast(right(#PairDt, 5) as int), '1899-12-30'), DATEDIFF(day, '1899-12-30', #Day)

Convert packed DB2 iseries value to YYYY-MM-DD

I'm trying to select records from a DB2 Iseries system where the date field is greater than the first of this year.
However, the date fields I'm selecting from are actually PACKED fields, not true dates.
I'm trying to convert them to YYYY-MM-DD format and get everything greater than '2018-01-01' but no matter what I try it says it's invalid.
Currently trying this:
SELECT *
FROM table1
WHERE val = 145
AND to_date(char(dateShp), 'YYYY-MM-DD') >= '2018-01-01';
it says expression not valid using format string specified.
Any ideas?
char(dateshp) is going to return a string like '20180319'
So your format string should not include the dashes.. 'YYYYMMDD'
example:
select to_date(char(20180101), 'YYYYMMDD')
from sysibm.sysdummy1;
So your code should be
SELECT *
FROM table1
WHERE val = 145
AND to_date(char(dateShp), 'YYYYMMDD') >= '2018-01-01';
Charles gave you a solution that converts the Packed date to a date field, and if you are comparing to another date field, this is a good solution. But if you are comparing to a constant value or another numeric field, you could just use something like this:
select *
from table1
where val = 145
and dateShp >= 20180101;

How can I compare two datetime fields but ignore the year?

I get to dust off my VBScript hat and write some classic ASP to query a SQL Server 2000 database.
Here's the scenario:
I have two datetime fields called fieldA and fieldB.
fieldB will never have a year value that's greater than the year of fieldA
It is possible the that two fields will have the same year.
What I want is all records where fieldA >= fieldB, independent of the year. Just pretend that each field is just a month & day.
How can I get this? My knowledge of T-SQL date/time functions is spotty at best.
You may want to use the built in time functions such as DAY and MONTH. e.g.
SELECT * from table where
MONTH(fieldA) > MONTH(fieldB) OR(
MONTH(fieldA) = MONTH(fieldB) AND DAY(fieldA) >= DAY(fieldB))
Selecting all rows where either the fieldA's month is greater or the months are the same and fieldA's day is greater.
select *
from t
where datepart(month,t.fieldA) >= datepart(month,t.fieldB)
or (datepart(month,t.fieldA) = datepart(month,t.fieldB)
and datepart(day,t.fieldA) >= datepart(day,t.fieldB))
If you care about hours, minutes, seconds, you'll need to extend this to cover the cases, although it may be faster to cast to a suitable string, remove the year and compare.
select *
from t
where substring(convert(varchar,t.fieldA,21),5,20)
>= substring(convert(varchar,t.fieldB,21),5,20)
SELECT *
FROM SOME_TABLE
WHERE MONTH(fieldA) > MONTH(fieldB)
OR ( MONTH(fieldA) = MONTH(fieldB) AND DAY(fieldA) >= DAY(fieldB) )
I would approach this from a Julian date perspective, convert each field into the Julian date (number of days after the first of year), then compare those values.
This may or may not produce desired results with respect to leap years.
If you were worried about hours, minutes, seconds, etc., you could adjust the DateDiff functions to calculate the number of hours (or minutes or seconds) since the beginning of the year.
SELECT *
FROM SOME_Table
WHERE DateDiff(d, '1/01/' + Cast(DatePart(yy, fieldA) AS VarChar(5)), fieldA) >=
DateDiff(d, '1/01/' + Cast(DatePart(yy, fieldB) AS VarChar(5)), fieldB)
Temp table for testing
Create table #t (calDate date)
Declare #curDate date = '2010-01-01'
while #curDate < '2021-01-01'
begin
insert into #t values (#curDate)
Set #curDate = dateadd(dd,1,#curDate)
end
Example of any date greater than or equal to today
Declare #testDate date = getdate()
SELECT *
FROM #t
WHERE datediff(dd,dateadd(yy,1900 - year(#testDate),#testDate),dateadd(yy,1900 - year(calDate),calDate)) >= 0
One more example with any day less than today
Declare #testDate date = getdate()
SELECT *
FROM #t
WHERE datediff(dd,dateadd(yy,1900 - year(#testDate),#testDate),dateadd(yy,1900 - year(calDate),calDate)) < 0