Как сделать запрос дней рождений за месяц без учета года

Автор Smopuim_81, 15 октября 2015, 18:23

0 Пользователи и 1 гость просматривают эту тему.

Smopuim_81

Имеется libreoffice base подключенный к базе postgresql.

Есть также таблица "CHILDS" с колонкой дней рождений "BIRTH_CHILD"

необходимо сделать запрос, где выбирается список детей, у которых дни рождения будут от сегодняшнего дня на месяц вперед естественно без учета года рождения? Соответственно в случае, если текущая дата выпадает на декабрь, то выборка будет с этой даты до такой же даты января!

По логике интервал должен выглядеть так: WHERE "BIRTH_CHILD" BETWEEN CURRENT_DATE AND CURRENT_DATE + INTERVAL "30 days"

Делаю такой запрос:
SELECT "CHILDS"."BIRTH_CHILD", "CHILDS"."NAME_CHILD"
  FROM "public"."CHILDS" AS "CHILDS",
  WHERE to_char( "CHILDS"."BIRTH_CHILD", 'DD.MM' ) BETWEEN to_char( CURRENT_DATE, 'DD.MM' ) AND to_char( CURRENT_DATE + INTERVAL "30 days", 'DD.MM' )
   ORDER BY "CHILDS"."BIRTH_CHILD" ASC

И получаю синтаксическую ошибку в BASE:
Состояние SQL: HY000
Код ошибки: 1000
syntax error, unexpected $end, expecting BETWEEN or IN or SQL_TOKEN_LIKE

Думаю вся проблема в INTERVAL, только как выбрать промежуток времени в postgresql ума не приложу. Весь инет перерыл уже! Помогите кто в этом разбирается! Буду очень признателен! :beer:

rami

#1
Цитата: Smopuim_81 от 15 октября 2015, 16:23По логике интервал должен выглядеть так: WHERE "BIRTH_CHILD" BETWEEN CURRENT_DATE AND CURRENT_DATE + INTERVAL "30 days"
В родной Base работает:SELECT * FROM "CHILDS" WHERE MONTH( "BIRTH_CHILD" ) = MONTH( CURRENT_DATE ) AND DAY( "BIRTH_CHILD" ) >= DAY( CURRENT_DATE ) OR MONTH( "BIRTH_CHILD" ) = CASEWHEN( MONTH( CURRENT_DATE ) = 12, 1, MONTH( CURRENT_DATE ) + 1 ) AND DAY( "BIRTH_CHILD" ) < DAY( CURRENT_DATE ) ORDER BY "BIRTH_CHILD" ASC

Smopuim_81

Цитата: rami от 16 октября 2015, 11:21
Цитата: Smopuim_81 от 15 октября 2015, 16:23По логике интервал должен выглядеть так: WHERE "BIRTH_CHILD" BETWEEN CURRENT_DATE AND CURRENT_DATE + INTERVAL "30 days"
В родной Base работает:SELECT * FROM "CHILDS" WHERE MONTH( "BIRTH_CHILD" ) = MONTH( CURRENT_DATE ) AND DAY( "BIRTH_CHILD" ) >= DAY( CURRENT_DATE ) OR MONTH( "BIRTH_CHILD" ) = CASEWHEN( MONTH( CURRENT_DATE ) = 12, 1, MONTH( CURRENT_DATE ) + 1 ) AND DAY( "BIRTH_CHILD" ) < DAY( CURRENT_DATE ) ORDER BY "BIRTH_CHILD" ASC

На данный запрос получил ошибку: Код ошибки: 1

pq_driver: [PGRES_FATAL_ERROR]ERROR:  function month(date) does not exist
LINE 1: SELECT * FROM "CHILDS" WHERE MONTH( "BIRTH_CHILD" ) = MONTH(...
                                     ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
(caused by statement 'SELECT * FROM "CHILDS" WHERE MONTH( "BIRTH_CHILD" ) = MONTH( CURRENT_DATE ) AND DAY( "BIRTH_CHILD" ) >= DAY( CURRENT_DATE ) OR MONTH( "BIRTH_CHILD" ) = CASEWHEN( MONTH( CURRENT_DATE ) = 12, 1, MONTH( CURRENT_DATE ) + 1 ) AND DAY( "BIRTH_CHILD" ) < DAY( CURRENT_DATE ) ORDER BY "BIRTH_CHILD" ASC')

Я думаю тут есть нестыковка между операторами BASE  и postgresql. Какие-то драйвер pq_driver хавает, а какие-то не понимает. Например в документации psql четко написано как добавить к текущей дате интервал, но BASE не понимает параметр interval и ругается на синтаксис SQL.

Твою логику по переходу на следующий год я понял, хотя думаю сам psql с параметром интервал должен делать это автоматически. Допустим если к 'timestamp' (который находится в декабре) прибавить интервал месяц, то значение должно быть в январе следующего года. Если отсеить значение года в итоге должно без костылей все получиться. Но это мое мнение основанное на документации к постгрес.

Smopuim_81

А может вместо MONTH( "BIRTH_CHILD" ) сделать to_char( "CHILDS"."BIRTH_CHILD", 'MM' ) и по аналогии для года и дня?

Smopuim_81

Неее.. такое не проканает поскольку to_char приводит дату к string

rami

Цитата: Smopuim_81 от 16 октября 2015, 11:16Например в документации psql четко написано как добавить к текущей дате интервал, но BASE не понимает параметр interval и ругается на синтаксис SQL.

А если без interval ? В документации есть пример:date '2001-09-28' + integer '7'   получается:   date '2001-10-05'

Цитата: Smopuim_81 от 16 октября 2015, 11:16Допустим если к 'timestamp' (который находится в декабре) прибавить интервал месяц, то значение должно быть в январе следующего года.
Почему timestamp, а не date ??? нужны секунды момента рождения ???

Smopuim_81

Сделал так:

SELECT * FROM "CHILDS" WHERE EXTRACT( MONTH FROM "BIRTH_CHILD" ) = EXTRACT( MONTH FROM CURRENT_DATE ) AND EXTRACT( DAY FROM "BIRTH_CHILD" ) >= EXTRACT( DAY FROM CURRENT_DATE ) OR EXTRACT( MONTH FROM "BIRTH_CHILD" ) = CASEWHEN( EXTRACT( MONTH FROM CURRENT_DATE ) = 12, 1, EXTRACT( MONTH FROM CURRENT_DATE ) + 1 ) AND EXTRACT( DAY FROM "BIRTH_CHILD" ) < EXTRACT( DAY FROM CURRENT_DATE ) ORDER BY "BIRTH_CHILD" ASC

но pg_driver не понравилось наверно то, что внутри оператора есть возвращаемое значение в типе data "EXTRACT( MONTH FROM CURRENT_DATE ) + 1" вот что он пишет:
pq_driver: [PGRES_FATAL_ERROR]ERROR:  function casewhen(boolean, integer, double precision) does not exist
LINE 1: ...T_DATE ) OR EXTRACT( MONTH FROM "BIRTH_CHILD" ) = CASEWHEN( ...
                                                            ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

Smopuim_81

Цитата: Smopuim_81 от 16 октября 2015, 11:43Почему timestamp, а не date Непонимающий нужны секунды момента рождения Непонимающий

неее, секунды не нужны.. я под этим имел ввиду возвращаемое значение NOW(), попутался немного  ))

Smopuim_81

С integer такой запрос не прокатил:
SELECT * FROM "CHILDS" WHERE  "BIRTH_CHILD" = CURRENT_DATE + integer '30'     ORDER BY "BIRTH_CHILD" ASC

BASE ругается на синтаксическую ошибку в выражении SQL

Smopuim_81

Урра! Сделал! Вот этот запрос:

SELECT * FROM "CHILDS" WHERE EXTRACT( 'month' FROM age(CURRENT_DATE, "BIRTH_CHILD") ) >= 11  ORDER BY to_timestamp(to_char("BIRTH_CHILD", 'ddmm'), 'ddmm') ASC
Здесь 11 - это количество месяцев в году от месяца рождения до текущего месяца, то есть за месяц до нового дня рождения . Если надо сделать выборку за два месяца до дня рождения, то вместо 11 пишем соответственно 10  (получается путем: количество месяцев в году - количество месяцев до дня рождения =12-2=10.

Поскольку функция age возвращает интервал, то даже, если день рождения в декабре, sql сам считает интервал без лишних костылей!


ORDER BY to_timestamp(to_char("BIRTH_CHILD", 'ddmm'), 'ddmm')  - сортировка дат без учета года

Спасибо всем, кто пытался помочь!