SQL базы данных, не зависящий от базы данных, для возврата списка дат рождения, который хранится в виде метки времени - PullRequest
1 голос
/ 15 мая 2009

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

т.е.
Хранится как 01-JAN-50 10.22.06.000000000
Дата выбрана 01-ЯНВ-50 10.22.06.010101120

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

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

Ответы [ 5 ]

2 голосов
/ 15 мая 2009

Тип Oracle DATE предшествует стандартной версии 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'
1 голос
/ 15 мая 2009

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

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

0 голосов
/ 15 мая 2009

Использовать EXTRACT ()

0 голосов
/ 15 мая 2009

Как уже отмечали другие, СУБД сильно расходятся, когда дело доходит до обработки времени. Если они действительно следовали стандарту 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)
0 голосов
/ 15 мая 2009

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

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

...