Независимый от базы данных SQL для возврата списка даты рождения, хранящегося в виде отметки времени.

StackOverflow https://stackoverflow.com/questions/868464

Вопрос

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

то есть
Хранится как 01-ЯНВ-50 22.10.06.000000000
дата выбрана 01.01.50 22.10.06.010101120

Если я использую дату с часами и минутами, SQL вернет только строки с точной отметкой времени, а не строки только для дня, месяца и года.

SQL должен работать на Oracle, SQLServer, MySQL и DB2.

Это было полезно?

Решение

Тип DATE Oracle предшествует стандартной версии SQL (как и версия Informix), что делает это чрезвычайно трудным, если не невозможным, сделать это нейтральным по отношению к СУБД образом.Конечно, возникает вопрос: «Почему выбранное представление данных включает время?»

В стандартном SQL очевидным методом было бы привести TIMESTAMP к DATE.У нас также нет четкого объяснения данных, по которым вам нужно искать.

SELECT CAST(DateOfBirth AS DATE), ...other columns...
    FROM TheMysteryTable         -- Why do people hate giving tables names?
    WHERE CAST(DateOfBirth AS DATE) =
          CAST(TIMESTAMP '1950-01-01 10.22.06.010101120' AS DATE)

Но это предполагает, что вы пишете «дату для поиска» как литерал.Если это переменная хоста, то тип переменной хоста должен быть DATE, а не TIMESTAMP.И столбец DateOfBirth, вероятно, должен быть DATE, а не TIMESTAMP.Вам не следует использовать TIMESTAMP, если временная часть не имеет значения — это тратит впустую память и время вычислений.

Обратите внимание, что из-за приведения маловероятно, что СУБД сможет использовать какие-либо индексы или что-то еще.Если бы типы были нормальными, то запрос был бы простым:

SELECT DateOfBirth, ...other columns...
    FROM TheMysteryTable
    WHERE DateOfBirth = DATE '1950-01-01'

Другие советы

Поскольку любое решение потребует манипулирования объектами date и datetime, тогда не будет системно-зависимого решения — каждое из них будет иметь разные функции для этих объектов.

Лучшим решением, кроме абстракции базы данных, было бы сначала округлить используемый объект datetime, а затем потребуется только общее предложение сравнения SQL, которое будет работать во всех перечисленных БД.

Нет формата даты ANSI и манипуляций со строками.Любой код будет работать только в определенных СУБД, если не в одной.

Однако, если вы получаете выбранную дату за пределами вашей СУБД (скажем, PHP, Java и т. д.), я бы предложил очистить ее перед отправкой в ​​запросе;затем вы можете сравнить строку со строкой, что должно работать практически во всех системах.

Как отмечали другие, СУРБД очень различаются в том, что касается обработки дат и времени. Если они фактически следовали стандарту ANSI-92, тогда должно работать следующее:

SELECT
     <column list>
FROM
     <table name>
WHERE
     CAST(birth_date AS DATE) = CAST(search_date AS DATE)

Однако это не самый эффективный способ сделать это, поскольку в большинстве систем он исключает использование индексов по дате.Следующее мощь работать с базой данных, полностью совместимой с ANSI-92:

SELECT
     <column list>
FROM
     <table name>
WHERE
     birth_date >= CAST(CAST(search_date AS DATE) AS DATETIME) AND
     birth_date < CAST(CAST(search_date AS DATE) + 1 AS DATETIME)

Используйте ИЗВЛЕЧЕНИЕ()

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top