How to tweak the SET intervalstyle (change the Interval Output) in PostgreSQL? - postgresql

I have read in this online PostgreSQL documentation... http://www.postgresql.org/docs/9.4/static/datatype-datetime.html#INTERVAL-STYLE-OUTPUT-TABLE
in the point 8.5.5 something about how to tweak the default Interval Output. . I mean the default interval is shown like this...
00:00:00.000 (if the timedifference is lower than a day or month or year)
1 day 00:00:00.000 (if the timedifference reaches days, but is lower than a month or a year)
1 month 1 day 00:00:00.000 (if the timediffence reaches months, but is lower than a year)
1 year 1 month 1 day 00:00:00.000 (if it reaches years, months, days)
it evens uses plurarl cases (years, mons, days) when their values are greater than one.
All these variations make difficult to any other app when SELECTing (query) this interval values (as text) to convert it to a proper time. So I would like postgresql to always show year, month n days, even if their value are 0 (it could be even better if it could show the date part of the interval like this... 01-11-30, adding zeros to the left side when values are less than ten)
I know I can change the interval to text, using to_char() but I really would like to avoid that, I would like some good fellow postgresql programmer to tell me if it is true that there is a way to tweak the Interval Output as is said in the postgresql documentation.
Thanks Advanced.
PD: two more links about the subject
https://my.vertica.com/docs/7.1.x/HTML/Content/Authoring/SQLReferenceManual/Statements/SET/SETDATESTYLE.htm
http://my.vertica.com/docs/6.1.x/HTML/index.htm#13874.htm

You can set the interval output style, but only to one of a few pre-defined formats that are unambigious on input, and that PostgreSQL knows how to parse back into intervals. Per the documentation these are the SQL standard interval format, two variants of PostgreSQL specific syntax, and iso_8601 intervals.
If you want something familiar and easy to parse, consider using:
SET intervalstyle = 'iso_8601'
and using an off-the-shelf parser for ISO1601 intervals.

Related

how to count week number of month using dataprep

I tried to count week number of month using below code,but I got weird num like -48.(I know my logic is weird lol)
Could you point out the fault of below code to make weeknum of month.
I need sensei's help.
I used Dataprep
WEEKNUM(date)-WEEKNUM(DATE(YEAR(date),MONTH(date),1))
no error , but some values are -48,47......
Your logic is mostly sound, except you're only thinking of WEEKNUM in the context of a single year. In order to have non-overlapping weeks, the week containing January 1 is always week 1 (regardless of the period), so in this case December 29–31, 2019 are all going to be week 1, just like the following 4 days of January will be. It makes sense, but only when you think about it in context of multiple years.
You can work around this for your case by checking the WEEKNUM and MONTH values conditionally, and then outputting a different value:
IF(AND(MONTH(date) == 12,WEEKNUM(date) == 1),53,WEEKNUM(date)) - WEEKNUM(DATE(YEAR(date),MONTH(date),1))
While hard-coding the week number of 53 is a little hacky, the whole point of week numbers is to always have 52 subdivisions—so I don't really see any concerns there.
You may also want to add 1 to the resulting formula (unless you want your week numbers to start with 0 each month).

inconsistency between month, day, second representation of interval data type

I understand why postgresql uses month,day and second fields to representate the sql interval datatype. A month is not always the same length and a day can have 23, 24 or 25 hours if a daylight savings time adjustment is involved. this is from postgresql documentation.
But I then do not understand why this is not consequently handled both for months and days. see the following query which calculates an exact interval where the number of seconds between two points in time is exactly calculatable:
select ('2017-01-01'::timestamp-'2016-01-01'::timestamp); -->366 days.
postgresql chooses to give a result in days. not in months and not in seconds.
But why is the result days and not seconds? it is NOT defined how long days are (they can be 23,24 or 25 hours long). so why does he not give output in seconds?
Then since the length of months is also not defined, why doesn't postgresql give an output of 12 month instead of 366 days?
He does not care that the length of days is not defined, but obviously he cares that the length of month is not defined.
Why this asymmetrie?
For further explanation, see this query:
select ('10 days'::interval-'24 hours'::interval); --> 10 days -24:00:00
you see that postgresql correctly refuses to answer with 9 days. He is pretty aware of the problem that days and hours cannot be interchanged. But then again why does the first query return days?
I can't answer your question, but I think I can point you in the right direction. I think the book SQL-99 Complete, Really is the most accessible source for understanding SQL intervals. It's available online: https://mariadb.com/kb/en/sql-99/08-temporal-values/.
SQL standards describe two kinds of intervals: year-month intervals and day-time intervals. It does this to prevent month parts and day parts from appearing in the same interval, because, as you already know, the number of days in a month is ambiguous. The number of days in the interval '3' month depends on which three months you're talking about.
I think this is the verbose, standard SQL way to write your first query.
select cast(timestamp '2017-01-01' - timestamp '2016-01-01' as interval day to hour) as new_column;
new_column
interval day to hour
--
366 days
I suspect that you'll find that SQL standards have rules for what a SQL dbms is supposed to do when things like interval day to hour are omitted. PostgreSQL might or might not follow those rules.
postgresql chooses to give a result in days. not in months and not in seconds.
Standard SQL prevents month parts and day parts from appearing in the same interval. Also, the range of valid seconds is from 0 to 59.
select interval '59' second;
interval
interval second
--
00:00:59
select interval '60' second;
interval
interval second
--
00:01:00

Postgres - Convert Date Range to Individual Month

I have found similar help, but the issue was more complex, I am only good with the basics of SQL and am striking out here. I get a handful of columns a,b,c,startdate,enddate and i need to parse that data out into multiple rows depending on how many months are within the range.
Eg: a,b,c,1/1/2015, 3/15,2015 would become:
a,b,c,1/1/2015,value_here_doesnt_matter
a,b,c,2/1/2015,value_here_doesnt_matter
a,b,c,3/1/2015,value_here_doesnt_matter
Does not matter if the start date or end date is on a specific day, the only thing that matters is month and year. So if the range included any day in a given month, I'd want to output start days for each month in the range, with the 1st as a default day.
Could I have any advice on which direction to begin? I'm attempting generate_series, but am unsure if this is the right approach or how to make it work with keeping the data in the first few arbitrary columns consistent.
I think generate_series is the way to go. Without knowing what the rest of your data looks like, I would start with something like this:
select
a, b, c, generate_series(startdate, enddate, interval '1 month')::date
from
my_table

how to change the first day of the week in PostgreSQL

I need to change the week start date from Monday to Saturday in PostgreSQL. I have tried SET DATEFIRST 6; but it doesn't work in PostgreSQL. Please suggest solution for this.
It appears that DATEFIRST is a thing in Microsoft Transact-SQL.
I don't believe Postgres has any exact equivalent, but you should be able to approximate it.
Postgres supports extracting various parts of a TIMESTAMP via the EXTRACT function. For your purposes, you would want to use either DOW or ISODOW.
DOW numbers Sunday (0) through Saturday (6), while ISODOW, which adheres to the ISO 8601 standard, numbers Monday (1) through Sunday (7).
From the Postgres doc:
This:
SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-18 20:38:40');
Returns 0, while this:
SELECT EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40');
Returns 7.
So you would use a version of EXTRACT in your queries to get the day of the week number. If you're going to use it in many queries, I would recommend creating a function which would centralize the query in one spot, and return the number transposed as you would like such that it started on Saturday (the transposition would vary depending on which numbering method you used in EXTRACT). Then you could simply call that function in any SELECT and it would return the transposed number.
You can just add +x, where x is the offset between postgres dow and what you want to achieve.
For example:
You want Sunday to be the first day of the week. 2018-06-03 is a Sunday and you want to extract the dow of it:
SELECT EXTRACT(DOW FROM DATE '2018-06-03')+1;
returns 1
That is probably the reason why postgres dow yields 0 for Sunday. Would it be 7, then
SELECT EXTRACT(DOW FROM DATE '2018-06-03')+1;
would return 8.

DB2 convert long value to timestamp

Is there a scalar function in DB2 to convert a long number to TIMESTAMP?
As #Dan1111 points out; no, there's nothing built in.
However, if you've got a 'long' number (I'm assuming BIGINT), I'm guessing you have a count of seconds (or similar) from the Unix Epoch (1970-01-01 00:00:00.000 UTC). If so, it's easy to 'cheat', and you can use this logic to write your own:
SELECT TIMESTAMP('1970-01-01', '00:00:00') + <your_column> SECONDS
FROM <your_table>
This of course presumes that the count is actually from UTC (and that you plan to interpret the results as such), as daylight savings time (and timezones, to a lesser extent) screws things up royally.
A quick example:
SELECT TIMESTAMP('1970-01-01', '00:00:00') + 1348241581 SECONDS
FROM sysibm/sysdummy1
Yields the expected:
2012-09-21-15.33.01.000000
(GMT, obviously)