Abfrage von Öffnungszeiten

Hey,
ich weiß jetzt nicht ob es hier rein oder in den Bereich pl/pgsql gehört und zwar hab ich eine postgis datenbank in dieser befinden sich 2 tabellen

  • betriebe (alle notwendingen informationen über den betrieb)
  • öffnungszeiten (die öffnungszeiten der betriebe)

könnte mir jemand vielleicht helfen wie die abfrage aufgebaut sein muss um darzustellen welcher betrieb gerade offen hat?
Da jeder Betrieb verschiedene Öffnungszeiten hat, hab ich die Tabelle öffnungszeiten wie folgt aufgebaut:

[TABLE=“width: 500”]
[TR]
[TD]name
[/TD]
[TD]tag [/TD]
[TD]gueltigvon [/TD]
[TD]gueltigbis [/TD]
[TD]uhrvon [/TD]
[TD]uhrbis[/TD]
[/TR]
[TR]
[TD]betrieb A [/TD]
[TD]SA[/TD]
[TD]01.03.2012[/TD]
[TD]31.03.2012[/TD]
[TD]14:00[/TD]
[TD]22:00[/TD]
[/TR]
[TR]
[TD]betrieb A[/TD]
[TD]SO[/TD]
[TD]01.03.2012[/TD]
[TD]31.03.2012[/TD]
[TD]14:00[/TD]
[TD]22:00[/TD]
[/TR]
[TR]
[TD]betrieb A[/TD]
[TD]MO[/TD]
[TD]01.04.2012[/TD]
[TD]15.11.201[/TD]
[TD]14:00[/TD]
[TD]22:00[/TD]
[/TR]
[TR]
[TD]betrieb A[/TD]
[TD]DI[/TD]
[TD]01.04.2012[/TD]
[TD]15.11.201[/TD]
[TD]14:00[/TD]
[TD]22:00[/TD]
[/TR]
[TR]
[TD]betrieb A[/TD]
[TD]MI[/TD]
[TD]01.04.2012[/TD]
[TD]15.11.201[/TD]
[TD]14:00[/TD]
[TD]22:00[/TD]
[/TR]
[/TABLE]

Was hast Du denn bisher versucht? Welche Version hast Du am Start?

Ich hab mal was mit 9.2 versucht (Devel-Version), um RANGE-Typen zu verwenden, und festgestellt, daß es keine TIMERANGE gibt :frowning:

Aber egal:

test=*# create table dasx(name text, tag int, gueltig daterange, offen int4range);
CREATE TABLE
test=*# copy dasx from stdin;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> betrieb_a    6        [2012-03-01,2012-12-31)        [14,22)
>> \.
test=*# select * from dasx where gueltig @> current_date and offen @> 13;
 name | tag | gueltig | offen
------+-----+---------+-------
(0 rows)

test=*# select * from dasx where gueltig @> current_date and offen @> 15;
   name    | tag |         gueltig         |  offen
-----------+-----+-------------------------+---------
 betrieb_a |   6 | [2012-03-01,2012-12-31) | [14,22)
(1 row)

Also ich finde Range-Typen ja sowas von genial, mir fehlen quasi die Worte…

Andreas

Außerdem: die Community. Es hat nur etwas über 1 Stunde gedauert, nachdem ich in der Mailinglist fehlenden Datentyp TIMERANGE beklagte meldete sich Jeff Davis (der, der das maßgeblich programmiert hat), mit diesem schönen Einzeiler als Lösung:

CREATE TYPE timerange AS RANGE ( subtype = time );


Andreas

wow, also vielen dank mal für eure hilfe, naja ich kann leider nicht sagen welche version ich hab, da ich vom uniserver abhängig bin und keinen zugriff auf so eine information besitze!

also ich bin immer daran gehangen wie ich die aktuelle zeit auslese mit tag, monat und jahr umd diese dann mit meinem inhalt zu vergleichen bzw abzufragen. bin jetzt leider nicht der absolute experte, aber wenn ich das sehe muss ich wohl meine tabelle neu aufbauen, versteh ich das richtig? falls ja, gueltig mit daterange und offen als int4range kann ich leider nicht erstellen, da sagt er mir type does not exist!



kretschmer@tux:~$ psql-dev
Timing is on.
psql (9.2devel)
Type "help" for help.

test=# select version();
                                             version
-------------------------------------------------------------------------------------------------
 PostgreSQL 9.2devel on i686-pc-linux-gnu, compiled by gcc (Ubuntu 4.3.3-5ubuntu4) 4.3.3, 32-bit
(1 row)

Ja, nicht ganz aktuell, …

also ich bin immer daran gehangen wie ich die aktuelle zeit auslese mit tag, monat und jahr umd diese dann mit meinem inhalt zu vergleichen bzw abzufragen.

dafür gibt es Funktionen:

test=# select date_trunc('hour',now());
       date_trunc
------------------------
 2012-08-04 11:00:00+02
(1 row)

Time: 0,242 ms
test=*# select to_char(now(),'hh24');
 to_char
---------
 11
(1 row)

PostgreSQL: Documentation: 9.1: Date/Time Functions and Operators



bin jetzt leider nicht der absolute experte, aber wenn ich das sehe muss ich wohl meine tabelle neu aufbauen, versteh ich das richtig? falls ja, gueltig mit daterange und offen als int4range kann ich leider nicht erstellen, da sagt er mir type does not exist!

Ja, logisch, weil es ist unwahrscheinlich, daß da eine Beta-Version produktiv läuft. Range-Typen kommen erst mit 9.2, und 9.2 kommt sehr wahrscheinlich im September, und wir als Hoster werden es sehr wahrscheinlich spätestens im Oktober anbieten. Wir haben Kunden, die schon mit den Füßen scharren, zumindest einer liest hier auch mit :wink:


Andreas

Das kannst Du mit select version(); anzeigen. Aber ich gehe nicht davon aus, dass ihr eine Version an der Uni verwendet, die noch gar nicht released worden ist.

Mit Deiner Tabelle geht das eigentlich ganz einfach:

postgres=> create table betriebe (name text, tag integer, gueltigvon date, gueltigbis date, uhrvon time, uhrbis time);
CREATE TABLE
postgres=> insert into betriebe
postgres-> values
postgres-> ('betrieb A', 6, DATE '01.03.2012', date '31.12.2012', time '10:00 ', time '22:00'),
postgres-> ('betrieb A', 0, DATE '01.03.2012', date '31.12.2012', time '14:00 ', time '22:00'),
postgres-> ('betrieb A', 1, DATE '01.04.2012', date '15.11.2012', time '14:00 ', time '22:00'),
postgres-> ('betrieb A', 2, DATE '01.04.2012', date '15.11.2012', time '14:00 ', time '22:00'),
postgres-> ('betrieb A', 3, DATE '01.04.2012', date '15.11.2012', time '14:00 ', time '22:00');
INSERT 0 5
postgres=> commit;
COMMIT
postgres=> select current_timestamp as "Jetzt", name, tag, uhrvon, uhrbis
postgres-> from betriebe
postgres-> where current_date between gueltigvon and gueltigbis
postgres-> and current_time between uhrvon and uhrbis
postgres-> and extract(dow from current_date) = tag;
           Jetzt            |   name    | tag |  uhrvon  |  uhrbis
----------------------------+-----------+-----+----------+----------
 2012-08-04 11:21:51.656+02 | betrieb A |   6 | 10:00:00 | 22:00:00
(1 row)


postgres=>

Der einzige Unterschied zu Deiner Tabelle ist, dass ich den Wochentag als Nummer erwarte. Der Ausdruck extract(dow from current_date) liefert nämlich 0 für Sonntag, 1 für Montag usw. zurück. Wenn Du SO, MO, … in der Tabelle drin lassen willst musst Du das ein wenig umständlicher machen:

postgres=> create table betriebe (name text, tag text, gueltigvon date, gueltigbis date, uhrvon time, uhrbis time);
CREATE TABLE
postgres=>
postgres=> insert into betriebe
postgres-> values
postgres-> ('betrieb A', 'SA', DATE '01.03.2012', date '31.12.2012', time '10:00 ', time '22:00'),
postgres-> ('betrieb A', 'SO', DATE '01.03.2012', date '31.12.2012', time '14:00 ', time '22:00'),
postgres-> ('betrieb A', 'MO', DATE '01.04.2012', date '15.11.2012', time '14:00 ', time '22:00'),
postgres-> ('betrieb A', 'DI', DATE '01.04.2012', date '15.11.2012', time '14:00 ', time '22:00'),
postgres-> ('betrieb A', 'MI', DATE '01.04.2012', date '15.11.2012', time '14:00 ', time '22:00');
INSERT 0 5
postgres=>
postgres=> create table betriebe (name text, tag text, gueltigvon date, gueltigbis date, uhrvon time, uhrbis time);
CREATE TABLE
postgres=>
postgres=> insert into betriebe
postgres-> values
postgres-> ('betrieb A', 'SA', DATE '01.03.2012', date '31.12.2012', time '10:00 ', time '22:00'),
postgres-> ('betrieb A', 'SO', DATE '01.03.2012', date '31.12.2012', time '14:00 ', time '22:00'),
postgres-> ('betrieb A', 'MO', DATE '01.04.2012', date '15.11.2012', time '14:00 ', time '22:00'),
postgres-> ('betrieb A', 'DI', DATE '01.04.2012', date '15.11.2012', time '14:00 ', time '22:00'),
postgres-> ('betrieb A', 'MI', DATE '01.04.2012', date '15.11.2012', time '14:00 ', time '22:00');
INSERT 0 5
postgres=>
postgres=> select current_timestamp as "Jetzt", name, tag, uhrvon, uhrbis
postgres-> from betriebe
postgres-> where current_date between gueltigvon and gueltigbis
postgres-> and current_time between uhrvon and uhrbis
postgres-> and tag = case extract(dow from current_date)
postgres->              when 0 then 'SO'
postgres->              when 1 then 'MO'
postgres->              when 2 then 'DI'
postgres->              when 3 then 'MI'
postgres->              when 4 then 'DO'
postgres->              when 5 then 'FR'
postgres->              when 6 then 'SA'
postgres->           end;
           Jetzt            |   name    | tag |  uhrvon  |  uhrbis
----------------------------+-----------+-----+----------+----------
 2012-08-04 11:24:50.546+02 | betrieb A | SA  | 10:00:00 | 22:00:00
(1 row)

postgres=>



also ich bin immer daran gehangen wie ich die aktuelle zeit auslese mit tag, monat und jahr

Siehe current_date, current_time und current_timestamp

Mehr Informationen dazu finden sich im Handbuch: PostgreSQL: Documentation: 9.1: Date/Time Functions and Operators

[quote=“akretschmer”]

dafür gibt es Funktionen:
[code]
test=# select date_trunc('hour',now());
       date_trunc
------------------------
 2012-08-04 11:00:00+02
(1 row)

Time: 0,242 ms
test=*# select to_char(now(),'hh24');
 to_char
---------
 11
(1 row)

Ja, logisch, weil es ist unwahrscheinlich, daß da eine Beta-Version produktiv läuft. Range-Typen kommen erst mit 9.2, und 9.2 kommt sehr wahrscheinlich im September!

Andreas[/QUOTE]

Alles klar :slight_smile: das wäre ja sonst zu schön gewesen :slight_smile: so weit war ich auch schon, aber wie gesagt ich hab eben das problem wie ich das ganze in eine abfrage verpacke um eben zu wissen was gerade offen hat, irgendwie steh ich da total auf der leitung.

meine verison is übrigens

"PostgreSQL 8.3.7, compiled by Visual C++ build 1400"

also eine riesen großes dankeschön!!! echt damit is mir riesig geholfen!!

Das mit den Wochentagen ginge einfacher:

test=# select to_char(current_date + s * '1day'::interval, 'TMDY') from generate_Series(0,6)s;
 to_char
---------
 SA
 SO
 MO
 DI
 MI
 DO
 FR
(7 rows)

Also, einfach mit to_char() bei deutscher Lokalisierung den Wochentag berechnen anstatt dem CASE-Wurm :wink:


Andreas