powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите сделать выборку
7 сообщений из 7, страница 1 из 1
Помогите сделать выборку
    #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
Помогите сделать выборку
    #39034717
p2.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Viacheslav_mihalich,

Первая дата - t1, вторая дата - t2.
Выразить t1-start_time и t2-start_time в секундах и поделить каждую разность на период. Если первая разность между 0 и number_repetitions и ( целые части разностей не равны или первая разность целая ), то попадаем в интервал t1-t2.
...
Рейтинг: 0 / 0
Помогите сделать выборку
    #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
Помогите сделать выборку
    #39035159
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
Помогите сделать выборку
    #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
Помогите сделать выборку
    #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
Помогите сделать выборку
    #39038466
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
7 сообщений из 7, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите сделать выборку
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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