Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите сделать выборку / 7 сообщений из 7, страница 1 из 1
23.08.2015, 13:23
    #39034531
Viacheslav_mihalich
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите сделать выборку
Доброго дня!

Есть таблица:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
-- Table: "DOCTOR_CHANGES"

-- DROP TABLE "DOCTOR_CHANGES";

CREATE TABLE "DOCTOR_CHANGES"
(
  "ID" bigserial NOT NULL,
  "START_TIME" timestamp without time zone,
  "END_TIME" timestamp without time zone,
  "CREATION_TIME" timestamp without time zone,
  "CHANGE_TYPE_ID" integer NOT NULL,
  "INFORMATION" character varying(256),
  "DAY" integer,
  "PERIOD" integer,
  "NUMBER_REPETITIONS" integer,
  CONSTRAINT "DOCTOR_CHANGES_pkey" PRIMARY KEY ("ID"),
  CONSTRAINT "CHANGE_TYPE_ID_2" FOREIGN KEY ("CHANGE_TYPE_ID")
      REFERENCES "DOCTOR_CHANGE_TYPE_IDS" ("ID") MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE RESTRICT,
  CONSTRAINT day_of_week CHECK ("DAY"::numeric > 0::numeric AND "DAY"::numeric < 8::numeric),
  CONSTRAINT end_time_more_start_time CHECK ("END_TIME" > "START_TIME"),
  CONSTRAINT positive_change_type_id CHECK ("CHANGE_TYPE_ID" > 0),
  CONSTRAINT positive_period CHECK ("PERIOD" >= 0)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE "DOCTOR_CHANGES"
  OWNER TO postgres;

-- Index: "fki_CHANGE_TYPE_ID_2"

-- DROP INDEX "fki_CHANGE_TYPE_ID_2";

CREATE INDEX "fki_CHANGE_TYPE_ID_2"
  ON "DOCTOR_CHANGES"
  USING btree
  ("CHANGE_TYPE_ID");



Просьба помочь сделать выборку не только тех записей, у которых:
1. START_TIME лежит в промежутке между '2015-08-17' и '2015-08-23',
но и
2. START_TIME + i *PERIOD лежит в промежутке между '2015-08-17' и '2015-08-23'
где 1 <= i <= NUMBER_REPETITIONS.
PERIOD - количество секунд в периоде.

Пока что получилось выбрать записи, у кторорых
START_TIME или (START_TIME + NUMBER_REPETITIONS*PERIOD) лежат в промежутке между '2015-08-17' и '2015-08-23':

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
SELECT
"ID" as dchange_id,
"START_TIME" as start_time,
"PERIOD" as period,
"NUMBER_REPETITIONS" as repeat_number
FROM "DOCTOR_CHANGES"
WHERE 
 (("START_TIME" BETWEEN '2015-08-17' AND '2015-08-23') OR
 (("START_TIME" +  ("NUMBER_REPETITIONS" * "PERIOD")* interval '1 sec') BETWEEN '2015-08-17' AND '2015-08-23'))



Заранее спасибо!
...
Рейтинг: 0 / 0
24.08.2015, 09:43
    #39034717
p2.
p2.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите сделать выборку
Viacheslav_mihalich,

Первая дата - t1, вторая дата - t2.
Выразить t1-start_time и t2-start_time в секундах и поделить каждую разность на период. Если первая разность между 0 и number_repetitions и ( целые части разностей не равны или первая разность целая ), то попадаем в интервал t1-t2.
...
Рейтинг: 0 / 0
24.08.2015, 19:15
    #39035140
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите сделать выборку
Код: sql
1.
2.
3.
select * from (
    select *, "START_TIME" + generate_series(1, "NUMBER_REPETITIONS") * "PERIOD" * interval '1 sec' as test_time from "DOCTOR_CHANGES"
) as A where test_time BETWEEN '2015-08-01' AND '2015-09-01';




Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
rollback;

begin;

CREATE TABLE "DOCTOR_CHANGES"
(
  "ID" bigserial NOT NULL,
  "START_TIME" timestamp without time zone,
  "END_TIME" timestamp without time zone,
  "CREATION_TIME" timestamp without time zone,
  "CHANGE_TYPE_ID" integer ,-- NOT NULL,
  "INFORMATION" character varying(256),
  "DAY" integer,
  "PERIOD" integer,
  "NUMBER_REPETITIONS" integer,
  CONSTRAINT "DOCTOR_CHANGES_pkey" PRIMARY KEY ("ID"),
  -- CONSTRAINT "CHANGE_TYPE_ID_2" FOREIGN KEY ("CHANGE_TYPE_ID")
  --     REFERENCES "DOCTOR_CHANGE_TYPE_IDS" ("ID") MATCH SIMPLE
  --     ON UPDATE CASCADE ON DELETE RESTRICT,
  CONSTRAINT day_of_week CHECK ("DAY"::numeric > 0::numeric AND "DAY"::numeric < 8::numeric),
  CONSTRAINT end_time_more_start_time CHECK ("END_TIME" > "START_TIME"),
  CONSTRAINT positive_change_type_id CHECK ("CHANGE_TYPE_ID" > 0),
  CONSTRAINT positive_period CHECK ("PERIOD" >= 0)
);

INSERT into "DOCTOR_CHANGES"("ID", "START_TIME", "PERIOD", "NUMBER_REPETITIONS") VALUES
    (1, '2015-01-01', 3600, 10),
    (2, '2015-01-01', 2 * 30 * 24 * 3600, 10);

select * from (
    select *, "START_TIME" + generate_series(1, "NUMBER_REPETITIONS") * "PERIOD" * interval '1 sec' as test_time from "DOCTOR_CHANGES"
) as A where test_time BETWEEN '2015-08-01' AND '2015-09-01';


...
Рейтинг: 0 / 0
24.08.2015, 20:11
    #39035159
p2.
p2.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите сделать выборку
LeXa NalBat
Код: sql
1.
2.
3.
select * from (
    select *, "START_TIME" + generate_series(1, "NUMBER_REPETITIONS") * "PERIOD" * interval '1 sec' as test_time from "DOCTOR_CHANGES"
) as A where test_time BETWEEN '2015-08-01' AND '2015-09-01';

Если уж решил через гланды в жопу долбиться, не забивай на условие:Viacheslav_mihalich1. START_TIME лежит в промежутке между '2015-08-17' и '2015-08-23'
...
Рейтинг: 0 / 0
26.08.2015, 14:58
    #39036435
Viacheslav_mihalich
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите сделать выборку
Спасибо за ответы!

Воспользовался вариантом:

Код: plsql
1.
2.
3.
select * from (
    select *, "START_TIME" + generate_series(0, "NUMBER_REPETITIONS") * "PERIOD" * interval '1 sec' as test_time from "DOCTOR_CHANGES"
) as A where test_time BETWEEN '2015-08-01' AND '2015-09-01';



generate_series(0, "NUMBER_REPETITIONS") с нулем выбирает то, что надо,
включая условие:

Код: plsql
1.
1. START_TIME лежит в промежутке между '2015-08-17' и '2015-08-23'
...
Рейтинг: 0 / 0
28.08.2015, 10:20
    #39038141
LeXa NalBat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите сделать выборку
p2.,

Не согласен с вашей оценкой "через гланды в жопу".

Мой вариант с generate_series(0, "NUMBER_REPETITIONS") интуитивно понятен, он соответствует формулировке задачи "START_TIME + i *PERIOD ... где 1 <= i <= NUMBER_REPETITIONS".

Встречный вопрос, ваше вычисление "выразить t1-start_time и t2-start_time в секундах и поделить каждую разность на период" будет ли корректным с учетом возможного перехода на летнее/зимнее время?
...
Рейтинг: 0 / 0
28.08.2015, 13:57
    #39038466
p2.
p2.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите сделать выборку
LeXa NalBatинтуитивно понятенсубъективная оценка своих интеллектуальных способностей. Для кого-то и таблица умножения непостижима.

LeXa NalBatбудет ли корректным с учетом возможного перехода на летнее/зимнее время?в задаче и обозначено "without time zone", но даже, если ориентироваться на with time zone, арифметика интервалов инвариантна к переводу времени:
Код: sql
1.
2.
3.
4.
5.
6.
psql=# select (timestamp with time zone '2010-03-28 01:59:59 Europe/Moscow' + interval '1' second * 2) at time zone 'Europe/Moscow' "туда",
psql-#   extract(epoch from timestamp with time zone '2010-03-28 03:00:01 Europe/Moscow' - timestamp with time zone '2010-03-28 01:59:59 Europe/Moscow') "и обратно";
        туда         | и обратно
---------------------+-----------
 2010-03-28 03:00:01 |         2
(1 row)
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите сделать выборку / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]