Обсуждение: date interval
Hi All,
I need to generate a column representing the interval passed in months and
restrict the returned data to those intervals matching 12, 24, 36 and 48.
So far by reading the documentation I have gotten to these expressions. But I
do not know how to get the number of months out of this.
current_date - tbl_detail.ship_by_date AS elapsed_x
age(tbl_detail.ship_by_date) AS elapsed_y
Once I get that I am thinking that I can use the same expression with the IN
to get the desired results.
Any help on the expressions would be appreciated.
Kind Regards,
Keith
At 04:44 PM 5/4/05, Keith Worthington wrote:
>I need to generate a column representing the interval passed in months and
>restrict the returned data to those intervals matching 12, 24, 36 and 48.
>
>So far by reading the documentation I have gotten to these expressions. But I
>do not know how to get the number of months out of this.
>
> current_date - tbl_detail.ship_by_date AS elapsed_x
> age(tbl_detail.ship_by_date) AS elapsed_y
>
>Once I get that I am thinking that I can use the same expression with the IN
>to get the desired results.
date_part('epoch', age(tbl_detail.ship_by_date)) / (60*60) AS elapsed_y
instead of "IN (12,24,36,48)" you might also consider something like
where elapsed_y between 12 and 48 and elapsed_y %12 = 0
You'd have to run your own tests to see which is faster. An index might help:
date_part('epoch', age(tbl_detail.ship_by_date)) / (60*60)
or maybe (not sure if this one would get used):
( date_part('epoch', age(tbl_detail.ship_by_date)) / (60*60) ) % 12
Frank
At 07:12 PM 5/4/05, Frank Bax wrote:
>At 04:44 PM 5/4/05, Keith Worthington wrote:
>>I need to generate a column representing the interval passed in months and
>>restrict the returned data to those intervals matching 12, 24, 36 and 48.
>>
>>So far by reading the documentation I have gotten to these
>>expressions. But I
>>do not know how to get the number of months out of this.
>>
>> current_date - tbl_detail.ship_by_date AS elapsed_x
>> age(tbl_detail.ship_by_date) AS elapsed_y
>>
>>Once I get that I am thinking that I can use the same expression with the IN
>>to get the desired results.
>
>
>date_part('epoch', age(tbl_detail.ship_by_date)) / (60*60) AS elapsed_y
>
>instead of "IN (12,24,36,48)" you might also consider something like
> where elapsed_y between 12 and 48 and elapsed_y %12 = 0
>
>You'd have to run your own tests to see which is faster. An index might help:
> date_part('epoch', age(tbl_detail.ship_by_date)) / (60*60)
>or maybe (not sure if this one would get used):
> ( date_part('epoch', age(tbl_detail.ship_by_date)) / (60*60) ) % 12
Ooops, I thought you said hours - for months, something like this might work...
( date_part('year', xx) * 12 + date_part('month', xx) )
On Wed, 04 May 2005 19:18:33 -0400, Frank Bax wrote
> At 07:12 PM 5/4/05, Frank Bax wrote:
> >At 04:44 PM 5/4/05, Keith Worthington wrote:
> >>I need to generate a column representing the interval passed in months and
> >>restrict the returned data to those intervals matching 12, 24, 36 and 48.
> >>
> >>So far by reading the documentation I have gotten to these
> >>expressions. But I
> >>do not know how to get the number of months out of this.
> >>
> >> current_date - tbl_detail.ship_by_date AS elapsed_x
> >> age(tbl_detail.ship_by_date) AS elapsed_y
> >>
> >>Once I get that I am thinking that I can use the same expression with the IN
> >>to get the desired results.
> >
> >
> >date_part('epoch', age(tbl_detail.ship_by_date)) / (60*60) AS elapsed_y
> >
> >instead of "IN (12,24,36,48)" you might also consider something like
> > where elapsed_y between 12 and 48 and elapsed_y %12 = 0
> >
> >You'd have to run your own tests to see which is faster. An index might help:
> > date_part('epoch', age(tbl_detail.ship_by_date)) / (60*60)
> >or maybe (not sure if this one would get used):
> > ( date_part('epoch', age(tbl_detail.ship_by_date)) / (60*60) ) % 12
>
> Ooops, I thought you said hours - for months, something like this
> might work...
>
> ( date_part('year', xx) * 12 + date_part('month', xx) )
>
Frank,
Thanks for the post. Using your suggestion I have built the following query.
It works just fine. I am thinking about building a function to store the
repetitious part of the code. Mainly because, well, its ugly. I was
originally going off in another direction trying to find an elegant way to do
this using built in date functions. But hey, working ugly beats broke elegant
any day! :-)
SELECT tbl_detail.so_number,
tbl_detail.order_date,
tbl_detail.ship_by_date,
( ( date_part('year', current_date)::integer * 12::integer
+ date_part('month', current_date)::integer
) -
( date_part('year', tbl_detail.ship_by_date)::integer * 12::integer
+ date_part('month', tbl_detail.ship_by_date)::integer
)
) AS age_in_months
FROM tbl_detail
WHERE ( ( date_part('year', current_date)::integer * 12::integer
+ date_part('month', current_date)::integer
) -
( date_part('year', tbl_detail.ship_by_date)::integer * 12::integer
+ date_part('month', tbl_detail.ship_by_date)::integer
)
) BETWEEN 12 AND 48
AND ( ( date_part('year', current_date)::integer * 12::integer
+ date_part('month', current_date)::integer
) -
( date_part('year', tbl_detail.ship_by_date)::integer * 12::integer
+ date_part('month', tbl_detail.ship_by_date)::integer
)
) % 12::integer = 0
ORDER BY tbl_detail.so_number;
Kind Regards,
Keith
On Thu, 5 May 2005 10:39:23 -0400, Keith Worthington wrote
> On Wed, 04 May 2005 19:18:33 -0400, Frank Bax wrote
> > At 07:12 PM 5/4/05, Frank Bax wrote:
> > >At 04:44 PM 5/4/05, Keith Worthington wrote:
> > >>I need to generate a column representing the interval passed
> > >>in months and restrict the returned data to those intervals
> > >> matching 12, 24, 36 and 48.
> > >>
> > >>So far by reading the documentation I have gotten to these
> > >>expressions. But I do not know how to get the number of
> > >>months out of this.
> > >>
> > >> current_date - tbl_detail.ship_by_date AS elapsed_x
> > >> age(tbl_detail.ship_by_date) AS elapsed_y
> > >>
> > >>Once I get that I am thinking that I can use the same
> > >>expression with the IN to get the desired results.
> > >
> > >
> > > date_part('epoch', age(tbl_detail.ship_by_date)) / (60*60)
> > > AS elapsed_y
> > >
> > >instead of "IN (12,24,36,48)" you might also consider
> > >something like
> > > where elapsed_y between 12 and 48 and elapsed_y %12 = 0
> > >
> > >You'd have to run your own tests to see which is faster. An
> > >index might help:
> > > date_part('epoch', age(tbl_detail.ship_by_date)) / (60*60)
> > >or maybe (not sure if this one would get used):
> > > ( date_part('epoch', age(tbl_detail.ship_by_date))
> > > / (60*60) ) % 12
> >
> > Ooops, I thought you said hours - for months, something like this
> > might work...
> >
> > ( date_part('year', xx) * 12 + date_part('month', xx) )
> >
>
> Frank,
>
> Thanks for the post. Using your suggestion I have built the
> following query. It works just fine. I am thinking about building a
> function to store the repetitious part of the code. Mainly because,
> well, its ugly. I was originally going off in another direction
> trying to find an elegant way to do this using built in date
> functions. But hey, working ugly beats broke elegant any day! :-)
>
> SELECT tbl_detail.so_number,
> tbl_detail.order_date,
> tbl_detail.ship_by_date,
> ( ( date_part('year', current_date)::integer
> * 12::integer
> + date_part('month', current_date)::integer
> ) -
>
> ( date_part('year', tbl_detail.ship_by_date)::integer
> * 12::integer
> + date_part('month', tbl_detail.ship_by_date)::integer
> )
> ) AS age_in_months
> FROM tbl_detail
> WHERE ( ( date_part('year', current_date)::integer
> * 12::integer
> + date_part('month', current_date)::integer
> ) -
>
> ( date_part('year', tbl_detail.ship_by_date)::integer
> * 12::integer
> + date_part('month', tbl_detail.ship_by_date)::integer
> )
> ) BETWEEN 12 AND 48
> AND ( ( date_part('year', current_date)::integer
> * 12::integer
> + date_part('month', current_date)::integer
> ) -
>
> ( date_part('year', tbl_detail.ship_by_date)::integer
> * 12::integer
> + date_part('month', tbl_detail.ship_by_date)::integer
> )
> ) % 12::integer = 0
> ORDER BY tbl_detail.so_number;
>
> Kind Regards,
> Keith
Hi All,
Replying to myself.
I have figured out that I can use this expression:
( date_part( 'year',
age( date_trunc( 'month',
tbl_detail.ship_by_date
)
)
)::integer * 12::integer
+ date_part( 'month',
age( date_trunc( 'month',
tbl_detail.ship_by_date
)
)
)::integer
)
instead of the original one:
(
( date_part('year', current_date)::integer
* 12::integer
+ date_part('month', current_date)::integer
) -
( date_part('year', tbl_detail.ship_by_date)::integer
* 12::integer
+ date_part('month', tbl_detail.ship_by_date)::integer
)
)
While the first might be considered more elegant by some because it performs
the subtraction from the current date they both seem to function the same. I
doubt that there is a performance diff between the two but I am still a
newbie. HTH somebody someday.
Would anyone care to comment on the difference between
WHERE (expression) IN (12, 24, 36, 48)
and
WHERE (expression) BETWEEN 12 AND 48
AND (expression) % 12 = 0
I have not been able to see a measurable difference. Unfortunately, I am
working with a fairly small data set at this time.
Internally I believe the first WHERE clause is rewritten as
WHERE (expression) = 12
OR (expression) = 24
OR (expression) = 36
OR (expression) = 48
and the second WHERE clause is rewritten as
WHERE (expression) >= 12
AND (expression) <= 48
AND (expression) % 12 = 0
Kind Regards,
Keith