Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Помогите с запросом, PLEASE / 16 сообщений из 16, страница 1 из 1
10.01.2017, 11:31
    #39381308
Цветовод
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
Firebird v 2.5.

Есть таблица:
Код: sql
1.
2.
3.
4.
5.
6.
CREATE TABLE VAL_INT (
    ID       INTEGER NOT NULL,
    TAG      VARCHAR(10),
    VDATA    DATE,
    VTIME    TIME,
    VAL      INTEGER);


ID TAG VDATA VTIME VAL1 B 09.01.2017 06:00 02 A 09.01.2017 09:34 3333 A 09.01.2017 12:56 4444 A 09.01.2017 15:30 5555 B 09.01.2017 18:00 16 A 09.01.2017 19:15 07 A 10.01.2017 01:25 7778 A 10.01.2017 03:45 8889 A 10.01.2017 05:43 99910 B 10.01.2017 06:00 011 A 10.01.2017 07:21 111112 A 10.01.2017 08:17 2222
Мне надо:
1. Выбрать все значения для тэга A за период с 09.01.2017 по 10.01.2017
в обратном порядке по хронологии
2. Для каждого тэга A выбрать последнее предшествующее по времени
значение тэга B

12 A 10.01.2017 08:17 2222 10 B 10.01.2017 6:00 011 A 10.01.2017 07:21 1111 10 B 10.01.2017 6:00 0 9 A 10.01.2017 05:43 999 5 B 09.01.2017 18:00 1 8 A 10.01.2017 03:45 888 5 B 09.01.2017 18:00 1 7 A 10.01.2017 01:25 777 5 B 09.01.2017 18:00 1 6 A 09.01.2017 19:15 0 5 B 09.01.2017 18:00 1 4 A 09.01.2017 15:30 555 1 B 09.01.2017 6:00 0 3 A 09.01.2017 12:56 444 1 B 09.01.2017 6:00 0 2 A 09.01.2017 09:34 333 1 B 09.01.2017 6:00 0
Первое просто:

Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT V.ID, V.TAG, V.VDATA, V.VTIME, V.VAL
  FROM VAL_INT V
  WHERE 
      (V.TAG = :T) 
    AND
      (V.VDATA BETWEEN :B AND :E)
  ORDER BY V.VDATA DESC, V.VTIME DESC


А вот второе никак не получается.
Запросом вообще что-то даже мыслей нет, как сделать,
а в процедуре если пишу

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
...
  for SELECT V.ID, V.TAG, V.VDATA, V.VTIME, V.VAL
        FROM VAL_INT V
        WHERE ((V.TAG = :T) AND (V.VDATA BETWEEN :B AND :E))
        ORDER BY V.VDATA DESC, V.VTIME DESC
  into :ID, :TAG, :VDATA, :VTIME, :VAL
  do
  begin
    SELECT FIRST 1 B.VDATA, B.VTIME, B.VAL
      FROM VAL_INT B
      WHERE ((B.TAG = :R) AND ((B.VDATA <= :VDATA) AND (B.VTIME <= :VTIME)))
      ORDER BY B.VTIME DESC
    into :RDATA, :RTIME, :REFVAL;
    suspend;
    end
  end
...


получатся неправильно: ищется тэг "B", у которого И дата, И время меньше, чем у тэга "А".
То есть для тэгов "A" с ID 7, 8 и 9 тэг "B" найден не будет.
В общем, не выходить каменный цветок.

Подскажите, пожалуйста, куда грести?
...
Рейтинг: 0 / 0
10.01.2017, 11:40
    #39381320
WildSery
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
Цветовод,

Код: sql
1.
WHERE B.TAG = :R AND (B.VDATA <= :VDATA OR B.VDATA = :VDATA AND B.VTIME <= :VTIME)
...
Рейтинг: 0 / 0
10.01.2017, 11:42
    #39381323
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
Цветовод,

1. Надо было делать поле с типом timestamp а не разбивать на дату и время
2. В 3.0 см. функцию LAG
3. в 2.5 как-то так

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
  RDATA = NULL;
  RTIME = NULL;
  REFVAL = NULL;
  for SELECT V.ID, V.TAG, V.VDATA, V.VTIME, V.VAL
        FROM VAL_INT V
        WHERE ((V.TAG = :T) AND (V.VDATA BETWEEN :B AND :E))
        ORDER BY V.VDATA DESC, V.VTIME DESC
  into :ID, :TAG, :VDATA, :VTIME, :VAL
  do
  begin
    suspend;
    RDATA = VDATA;
    RTIME  = VTIME;
    REFVAL = VAL;
  end
...
Рейтинг: 0 / 0
10.01.2017, 11:46
    #39381328
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
Симонов Денис,

а у тебя там ещё и разбиение по tag есть
...
Рейтинг: 0 / 0
10.01.2017, 11:51
    #39381333
Цветовод
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
WildSery,
Неа, я так тоже пробовал. Не цветок.
...
Рейтинг: 0 / 0
10.01.2017, 11:55
    #39381336
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
Цветовод,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
...
  for SELECT V.ID, V.TAG, V.VDATA, V.VTIME, V.VAL
        FROM VAL_INT V
        WHERE ((V.TAG = :T) AND (V.VDATA BETWEEN :B AND :E))
        ORDER BY V.VDATA + V.VTIME DESC
  into :ID, :TAG, :VDATA, :VTIME, :VAL
  do
  begin
    SELECT FIRST 1 B.VDATA, B.VTIME, B.VAL
      FROM VAL_INT B
      WHERE (B.TAG = :R) AND (V.VDATA + V.VTIME <= :VDATA + :VTIME)
      ORDER BY V.VDATA + V.VTIME DESC
    into :RDATA, :RTIME, :REFVAL;
    suspend;
    end
  end
...



производительность будет ниже плинтуса. Пока не поздно добавь поле timestamp. Запрос сильно упроститься
...
Рейтинг: 0 / 0
10.01.2017, 11:55
    #39381337
WildSery
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
Цветовод,

Шарик, ты балбес (ц)

Неужели сам не видишь?
В одном месте написал ORDER BY V.VDATA DESC, V.VTIME DESC, а в другом, почему-то ORDER BY B.VTIME DESC
...
Рейтинг: 0 / 0
10.01.2017, 11:56
    #39381339
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
Цветовод,
FB правильно понимает вот такой синтаксис:
Код: sql
1.
((B.VDATA + B.VTIME) <= (:VDATA + :VTIME))


Попробуйте.
...
Рейтинг: 0 / 0
11.01.2017, 04:31
    #39381948
Цветовод
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
WildSeryШарик, ты балбес (ц)
За Шарика ответишь! )))
WildSeryВ одном месте написал ORDER BY V.VDATA DESC, V.VTIME DESC, а в другом, почему-то ORDER BY B.VTIME DESC
Не, не айс. Так всегда выбирается тэг с ID = 10, т.е. всегда срабатывает вторая часть WHERE (которая после OR).
...
Рейтинг: 0 / 0
11.01.2017, 04:42
    #39381949
Цветовод
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
Симонов Денис
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
...
  for SELECT V.ID, V.TAG, V.VDATA, V.VTIME, V.VAL
        FROM VAL_INT V
        WHERE ((V.TAG = :T) AND (V.VDATA BETWEEN :B AND :E))
        ORDER BY V.VDATA + V.VTIME DESC
  into :ID, :TAG, :VDATA, :VTIME, :VAL
  do
  begin
    SELECT FIRST 1 B.VDATA, B.VTIME, B.VAL
      FROM VAL_INT B
      WHERE (B.TAG = :R) AND (V.VDATA + V.VTIME <= :VDATA + :VTIME)
      ORDER BY V.VDATA + V.VTIME DESC
    into :RDATA, :RTIME, :REFVAL;
    suspend;
    end
  end
...

А вот это работает.
Симонов Дениспроизводительность будет ниже плинтуса.Не, не ниже. Она ваще никакая.)) Но это понятно.
Симонов ДенисПока не поздно добавь поле timestamp. Запрос сильно упроститьсяЯ не могу изменять типы полей. В базу пишет другая программа. Не моя. Это сервис сбора данных с оборудования. Без исходников.
Но я могу для себя добавить такое поле и формировать его триггером.
Я, конечно, протестирую такой вариант.
...
Рейтинг: 0 / 0
11.01.2017, 04:45
    #39381950
Цветовод
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
KreatorXXI, Денис обогнал тебя, но все равно спасибо.
...
Рейтинг: 0 / 0
11.01.2017, 04:49
    #39381951
Цветовод
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
Тут у меня возникла мысль - развернуть порядок выборки в процедуре - сначала дернуть все тэги "B",
а потом для каждого из них делать выборку "A".
Пойду-ка я эту мысль думать.
...
Рейтинг: 0 / 0
11.01.2017, 09:29
    #39382029
WildSery
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
ЦветоводНе, не айс. Так всегда выбирается тэг с ID = 10, т.е. всегда срабатывает вторая часть WHERE (которая после OR)."Вы что, за меня и есть будете?! - Ага!" (ц)
Написать "<" для вместо "<=" попробуй.
Мне показалось очевидным, что при сравнении на равенство в качестве предыдущей сама себя всегда выбирать будет.
...
Рейтинг: 0 / 0
11.01.2017, 10:33
    #39382065
hvlad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
Симонов Дениспроизводительность будет ниже плинтуса. Пока не поздно добавь поле timestampИли индекс по выражению, убывающий
...
Рейтинг: 0 / 0
11.01.2017, 13:07
    #39382238
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
ЦветоводKreatorXXI, Денис обогнал тебя, но все равно спасибо.
Не заметил. Сорри. Ну, акцентировал внимание на фиче, будем считать.
...
Рейтинг: 0 / 0
12.01.2017, 04:07
    #39382832
Цветовод
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом, PLEASE
hvladИли индекс по выражению, убывающийДелал VDATA + VTIME. Производительность растет, несущественно (где-то в 2,5 раза)

KreatorXXIНе заметил. Сорри. Ну, акцентировал внимание на фиче, будем считать. OK.

ЦветоводТут у меня возникла мысль - развернуть порядок выборки в процедуре - сначала дернуть все тэги "B",
а потом для каждого из них делать выборку "A".
Пойду-ка я эту мысль думать. Короче.
- Добавил поле TIMESTAMP (формируется в триггере BEFORE INSERT)
- Сделал по нему DESC индекс.
- в процедуре поменял порядок - см. выше.
Результат великолепный - все просто летает. Спасибо всем!
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Помогите с запросом, PLEASE / 16 сообщений из 16, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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