<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Temporal Keys, Part 2</title>
	<atom:link href="http://thoughts.j-davis.com/2009/11/08/temporal-keys-part-2/feed/" rel="self" type="application/rss+xml" />
	<link>http://thoughts.j-davis.com/2009/11/08/temporal-keys-part-2/</link>
	<description>Ideas on Databases, Logic, and Language by Jeff Davis</description>
	<lastBuildDate>Sat, 10 Jul 2010 14:36:49 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
	<item>
		<title>By: Jon Guiton</title>
		<link>http://thoughts.j-davis.com/2009/11/08/temporal-keys-part-2/comment-page-1/#comment-236</link>
		<dc:creator>Jon Guiton</dc:creator>
		<pubDate>Sat, 10 Jul 2010 14:36:49 +0000</pubDate>
		<guid isPermaLink="false">http://thoughts.j-davis.com/?p=180#comment-236</guid>
		<description>One concern I have for the PERIOD data type is the issue of whether the interval represented is open or closed i.e. is the endpoint included in the set of times ? In maths
intervals are represented using brackets (3..4) - open, doesn&#039;t include 3 or 4, just times in between; [3..4] closed, the set of times explicitly includes 3 and 4 or mixed (3..4] 3 is not included but 4 is. 

This is important since in a schedule two appointments will have a gap between them if the intervals are open (2..4),(4..6) implies nothing scheduled at 4 or will overlap if tey are closed [2..4],[4..6] double booking at 4. The correct solution is to use mixed intervals e.g (2..4], (4..6] now the complete interval is covered but there is no overlap.

There are many other cases where this is an issue, in fact it is an issue for any grouped data from a continuous set. If we want temporal keys to be sound we would need a solution that caters for this.</description>
		<content:encoded><![CDATA[<p>One concern I have for the PERIOD data type is the issue of whether the interval represented is open or closed i.e. is the endpoint included in the set of times ? In maths<br />
intervals are represented using brackets (3..4) &#8211; open, doesn&#8217;t include 3 or 4, just times in between; [3..4] closed, the set of times explicitly includes 3 and 4 or mixed (3..4] 3 is not included but 4 is. </p>
<p>This is important since in a schedule two appointments will have a gap between them if the intervals are open (2..4),(4..6) implies nothing scheduled at 4 or will overlap if tey are closed [2..4],[4..6] double booking at 4. The correct solution is to use mixed intervals e.g (2..4], (4..6] now the complete interval is covered but there is no overlap.</p>
<p>There are many other cases where this is an issue, in fact it is an issue for any grouped data from a continuous set. If we want temporal keys to be sound we would need a solution that caters for this.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ahmad Stjulien</title>
		<link>http://thoughts.j-davis.com/2009/11/08/temporal-keys-part-2/comment-page-1/#comment-221</link>
		<dc:creator>Ahmad Stjulien</dc:creator>
		<pubDate>Wed, 09 Jun 2010 18:25:14 +0000</pubDate>
		<guid isPermaLink="false">http://thoughts.j-davis.com/?p=180#comment-221</guid>
		<description>Thanks for sharing it for</description>
		<content:encoded><![CDATA[<p>Thanks for sharing it for</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: BillR</title>
		<link>http://thoughts.j-davis.com/2009/11/08/temporal-keys-part-2/comment-page-1/#comment-175</link>
		<dc:creator>BillR</dc:creator>
		<pubDate>Thu, 21 Jan 2010 03:19:40 +0000</pubDate>
		<guid isPermaLink="false">http://thoughts.j-davis.com/?p=180#comment-175</guid>
		<description>I tend to agree that millisecond precision might be overkill, but who is to know to what purpose Postgres will be put. I would not doubt that there is someone who would ask for this type of precision if you were to not provide it. ;) I know for certain that there are applications out there that definitely are down to the hour, as I found out returning my car an hour late to Avis Rent A Car.  :)

Anyway, I would suggest (or maybe second) the notion of finest granularity by default, and a mechanism (as you propose), to back off on the precision as needed.</description>
		<content:encoded><![CDATA[<p>I tend to agree that millisecond precision might be overkill, but who is to know to what purpose Postgres will be put. I would not doubt that there is someone who would ask for this type of precision if you were to not provide it. <img src='http://thoughts.j-davis.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  I know for certain that there are applications out there that definitely are down to the hour, as I found out returning my car an hour late to Avis Rent A Car.  <img src='http://thoughts.j-davis.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Anyway, I would suggest (or maybe second) the notion of finest granularity by default, and a mechanism (as you propose), to back off on the precision as needed.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jeff Davis</title>
		<link>http://thoughts.j-davis.com/2009/11/08/temporal-keys-part-2/comment-page-1/#comment-133</link>
		<dc:creator>Jeff Davis</dc:creator>
		<pubDate>Mon, 09 Nov 2009 17:56:38 +0000</pubDate>
		<guid isPermaLink="false">http://thoughts.j-davis.com/?p=180#comment-133</guid>
		<description>&lt;blockquote&gt;PERIOD needs some more docs and test cases as well.&lt;/blockquote&gt;

Yes. I&#039;ve been focusing on the core engine changes required, and Scott is working on the data types and their semantics.

&lt;blockquote&gt;first endpoint is inclusive and the second point is exclusive&lt;/blockquote&gt;

As a default, that&#039;s fine. But there are cases where you want an inclusive end time, as well.

&lt;blockquote&gt;Also think it would be useful to have a way to specify the granularity of the PERIOD.&lt;/blockquote&gt;

Scott had the same idea. I think this can be accomplished with a CHECK constraint, like
&lt;pre&gt;CHECK (
  first(during) = date_trunc(&#039;hour&#039;, first(during)) AND
  next(during) = date_trunc(&#039;hour&#039;, next(during))
)&lt;/pre&gt;
but it would be nice to make it a little easier to express.</description>
		<content:encoded><![CDATA[<blockquote><p>PERIOD needs some more docs and test cases as well.</p></blockquote>
<p>Yes. I&#8217;ve been focusing on the core engine changes required, and Scott is working on the data types and their semantics.</p>
<blockquote><p>first endpoint is inclusive and the second point is exclusive</p></blockquote>
<p>As a default, that&#8217;s fine. But there are cases where you want an inclusive end time, as well.</p>
<blockquote><p>Also think it would be useful to have a way to specify the granularity of the PERIOD.</p></blockquote>
<p>Scott had the same idea. I think this can be accomplished with a CHECK constraint, like</p>
<pre>CHECK (
  first(during) = date_trunc('hour', first(during)) AND
  next(during) = date_trunc('hour', next(during))
)</pre>
<p>but it would be nice to make it a little easier to express.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Scott Bailey</title>
		<link>http://thoughts.j-davis.com/2009/11/08/temporal-keys-part-2/comment-page-1/#comment-132</link>
		<dc:creator>Scott Bailey</dc:creator>
		<pubDate>Mon, 09 Nov 2009 17:01:40 +0000</pubDate>
		<guid isPermaLink="false">http://thoughts.j-davis.com/?p=180#comment-132</guid>
		<description>Simon,

A period defines a contiguous set of values but we can define it by the end points. The defaults are inclusive start, exclusive end.

I think if you gave from() a little more thought, you&#039;d change your mind.

I agree with you on being able to define the granularity. But my thought is that it would have to be set at the database level rather than say at the column level.

I&#039;d like to generalize the concept so that we&#039;ll be able to define a range of ints, dates, timestamps, numeric, etc.</description>
		<content:encoded><![CDATA[<p>Simon,</p>
<p>A period defines a contiguous set of values but we can define it by the end points. The defaults are inclusive start, exclusive end.</p>
<p>I think if you gave from() a little more thought, you&#8217;d change your mind.</p>
<p>I agree with you on being able to define the granularity. But my thought is that it would have to be set at the database level rather than say at the column level.</p>
<p>I&#8217;d like to generalize the concept so that we&#8217;ll be able to define a range of ints, dates, timestamps, numeric, etc.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Adrian Klaver</title>
		<link>http://thoughts.j-davis.com/2009/11/08/temporal-keys-part-2/comment-page-1/#comment-131</link>
		<dc:creator>Adrian Klaver</dc:creator>
		<pubDate>Mon, 09 Nov 2009 16:05:45 +0000</pubDate>
		<guid isPermaLink="false">http://thoughts.j-davis.com/?p=180#comment-131</guid>
		<description>Simon,
I don&#039;t know if you have access to the postgresqlconference.org site. If you do check out Scott Baileys talk on his temporal extensions to Postgres:

http://www.postgresqlconference.org/2009/west/talks/temporal_data

It is based on his CHRONOS project:
http://sourceforge.net/projects/chronosdb/

The extensions cover some of the points you raised.</description>
		<content:encoded><![CDATA[<p>Simon,<br />
I don&#8217;t know if you have access to the postgresqlconference.org site. If you do check out Scott Baileys talk on his temporal extensions to Postgres:</p>
<p><a href="http://www.postgresqlconference.org/2009/west/talks/temporal_data" rel="nofollow">http://www.postgresqlconference.org/2009/west/talks/temporal_data</a></p>
<p>It is based on his CHRONOS project:<br />
<a href="http://sourceforge.net/projects/chronosdb/" rel="nofollow">http://sourceforge.net/projects/chronosdb/</a></p>
<p>The extensions cover some of the points you raised.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: simon@2ndQuadrant.com</title>
		<link>http://thoughts.j-davis.com/2009/11/08/temporal-keys-part-2/comment-page-1/#comment-130</link>
		<dc:creator>simon@2ndQuadrant.com</dc:creator>
		<pubDate>Mon, 09 Nov 2009 13:23:46 +0000</pubDate>
		<guid isPermaLink="false">http://thoughts.j-davis.com/?p=180#comment-130</guid>
		<description>Jeff,

PERIOD needs some more docs and test cases as well.

The docs that are there describe PERIOD as a &quot;set&quot; rather than as two endpoints, which is how all examples are laid out. I think a PERIOD should have two endpoints (+/- infinity included). If you have need for a more fancy datatype it can have a slightly different name. So the next() and prior() functions just look a little overcooked. Better to have just from() and to() or similar.

Think it would be useful to have the default as the first endpoint is inclusive and the second point is exclusive, so they stack together neatly by default.

Also think it would be useful to have a way to specify the granularity of the PERIOD. In many cases a period is expressed only in days, not timestamps. For example in your hotel room example you don&#039;t book a hotel room for an exact second, you book one night at a time. Of course, some hotels do book by the hour, but very few by the second. It wouldn&#039;t be much use for businesses to refuse a booking because there was a 10ms overlap between 2 5 day bookings - nor would anybody really want to record that detail. 

So perhaps we need DATEPERIOD (2 DATEs) and TIMEPERIOD (2 TIMESTAMPs). It might be useful to be able to specify this like PERIOD(INTERVAL), so you can book holiday cottages in weeks, scaffolding by month etc.. Whatever the business needs.</description>
		<content:encoded><![CDATA[<p>Jeff,</p>
<p>PERIOD needs some more docs and test cases as well.</p>
<p>The docs that are there describe PERIOD as a &#8220;set&#8221; rather than as two endpoints, which is how all examples are laid out. I think a PERIOD should have two endpoints (+/- infinity included). If you have need for a more fancy datatype it can have a slightly different name. So the next() and prior() functions just look a little overcooked. Better to have just from() and to() or similar.</p>
<p>Think it would be useful to have the default as the first endpoint is inclusive and the second point is exclusive, so they stack together neatly by default.</p>
<p>Also think it would be useful to have a way to specify the granularity of the PERIOD. In many cases a period is expressed only in days, not timestamps. For example in your hotel room example you don&#8217;t book a hotel room for an exact second, you book one night at a time. Of course, some hotels do book by the hour, but very few by the second. It wouldn&#8217;t be much use for businesses to refuse a booking because there was a 10ms overlap between 2 5 day bookings &#8211; nor would anybody really want to record that detail. </p>
<p>So perhaps we need DATEPERIOD (2 DATEs) and TIMEPERIOD (2 TIMESTAMPs). It might be useful to be able to specify this like PERIOD(INTERVAL), so you can book holiday cottages in weeks, scaffolding by month etc.. Whatever the business needs.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: simon@2ndQuadrant.com</title>
		<link>http://thoughts.j-davis.com/2009/11/08/temporal-keys-part-2/comment-page-1/#comment-129</link>
		<dc:creator>simon@2ndQuadrant.com</dc:creator>
		<pubDate>Mon, 09 Nov 2009 13:11:22 +0000</pubDate>
		<guid isPermaLink="false">http://thoughts.j-davis.com/?p=180#comment-129</guid>
		<description>Tom, interesting post. Good solutions thinking.

The trigger method, as described, doesn&#039;t correctly handle concurrent inserts. That illustrates my main concern which is that there is too much code there and it is likely to have errors - I think you showed that in the number of posts taken as well. Anyhow, it is certainly slower than the in-database approach Jeff has designed.</description>
		<content:encoded><![CDATA[<p>Tom, interesting post. Good solutions thinking.</p>
<p>The trigger method, as described, doesn&#8217;t correctly handle concurrent inserts. That illustrates my main concern which is that there is too much code there and it is likely to have errors &#8211; I think you showed that in the number of posts taken as well. Anyhow, it is certainly slower than the in-database approach Jeff has designed.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tom Davis</title>
		<link>http://thoughts.j-davis.com/2009/11/08/temporal-keys-part-2/comment-page-1/#comment-128</link>
		<dc:creator>Tom Davis</dc:creator>
		<pubDate>Mon, 09 Nov 2009 09:40:08 +0000</pubDate>
		<guid isPermaLink="false">http://thoughts.j-davis.com/?p=180#comment-128</guid>
		<description>Wow! I did it again!

CREATE OR REPLACE FUNCTION dont_overlap_reservations() RETURNS trigger AS $$
DECLARE
  overlaps    text;
BEGIN
  SELECT whom INTO overlaps
    FROM  room_reservation
    WHERE room      = NEW.room
      AND beginning &lt;= NEW.until
      AND until     &gt;= NEW.beginning
      LIMIT 1;
  IF FOUND THEN
      RETURN NULL;
  ELSE
      RETURN NEW;
  END IF;
END;
$$ LANGUAGE plpgsql;</description>
		<content:encoded><![CDATA[<p>Wow! I did it again!</p>
<p>CREATE OR REPLACE FUNCTION dont_overlap_reservations() RETURNS trigger AS $$<br />
DECLARE<br />
  overlaps    text;<br />
BEGIN<br />
  SELECT whom INTO overlaps<br />
    FROM  room_reservation<br />
    WHERE room      = NEW.room<br />
      AND beginning &lt;= NEW.until<br />
      AND until     &gt;= NEW.beginning<br />
      LIMIT 1;<br />
  IF FOUND THEN<br />
      RETURN NULL;<br />
  ELSE<br />
      RETURN NEW;<br />
  END IF;<br />
END;<br />
$$ LANGUAGE plpgsql;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tom Davis</title>
		<link>http://thoughts.j-davis.com/2009/11/08/temporal-keys-part-2/comment-page-1/#comment-127</link>
		<dc:creator>Tom Davis</dc:creator>
		<pubDate>Mon, 09 Nov 2009 09:38:56 +0000</pubDate>
		<guid isPermaLink="false">http://thoughts.j-davis.com/?p=180#comment-127</guid>
		<description>Sorry, forgot to escape the greater than and less than operators, the function should be

CREATE OR REPLACE FUNCTION dont_overlap_reservations() RETURNS trigger AS $$
DECLARE
  overlaps    text;
BEGIN
  SELECT whom INTO overlaps
    FROM  room_reservation
    WHERE room      = NEW.room
      AND beginning = NEW.beginning
      LIMIT 1;
  IF FOUND THEN
      RETURN NULL;
  ELSE
      RETURN NEW;
  END IF;
END;
$$ LANGUAGE plpgsql;


Plus, obviously, you would use a timestamp rather than a time,

and it&#039;s probably a good idea to declare (room,beginning,until) as the primary key. For more than five rows an index might be useful.</description>
		<content:encoded><![CDATA[<p>Sorry, forgot to escape the greater than and less than operators, the function should be</p>
<p>CREATE OR REPLACE FUNCTION dont_overlap_reservations() RETURNS trigger AS $$<br />
DECLARE<br />
  overlaps    text;<br />
BEGIN<br />
  SELECT whom INTO overlaps<br />
    FROM  room_reservation<br />
    WHERE room      = NEW.room<br />
      AND beginning = NEW.beginning<br />
      LIMIT 1;<br />
  IF FOUND THEN<br />
      RETURN NULL;<br />
  ELSE<br />
      RETURN NEW;<br />
  END IF;<br />
END;<br />
$$ LANGUAGE plpgsql;</p>
<p>Plus, obviously, you would use a timestamp rather than a time,</p>
<p>and it&#8217;s probably a good idea to declare (room,beginning,until) as the primary key. For more than five rows an index might be useful.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
