Sql поиск по дате: MySQL. Как правильно искать по дате и времени? — Хабр Q&A

Содержание

SQL запросы в ORACLE / LIKE TO_DATE TO_NUMBER

Параметры или аргументы 

expression

Символьное выражение, такие как поле или столбец.

pattern

Символьное выражение, которое содержит сопоставляемый шаблон. Шаблоны, которые вы можете выбрать:

групповой символ и пояснение
% Соответствует любой строке любой длины (в том числе нулевой длины)
_ Соответствует одному символу

escape_character

Необязательный. Позволяет проверять буквенные экземпляры для групповых символов, таких как % или _

Пример использования % (символ процент)

Первый пример Oracle оператора LIKE, который мы рассмотрим, предполагает использование группового символа %.

Рассмотрим, как % работает в Oracle операторе LIKE.

Мы хотим найти всех customers, чьи last_name начинается с ‘Ар

’.

SELECT last_name FROM customers WHERE last_name LIKE ‘Ap%’;

SELECT last_name

FROM customers

WHERE last_name LIKE ‘Ap%’;

В этом примере Oracle оператора LIKE, мы ищем для всех customers, чьи last_name содержит символы ‘er

SELECT last_name FROM customers WHERE last_name LIKE ‘%er%’;

SELECT last_name

FROM customers

WHERE last_name LIKE ‘%er%’;

Пример использования _ (символ подчеркивание)

В этом примере Oracle LIKE вернет всех suppliers, чье supplier_name

имеет длину 5 символов, где первые два символа является ‘Sm’, а последние два символа это ‘th’. Например, он может вернуть suppliers, чьи supplier_name являются ‘Smith’, ‘Smyth’, ‘Smath’ или ‘Smeth’ и т.д.

Функция EXTRACT — части даты или даты-времени

Функция EXTRACT извлекает отдельные части из даты или даты-времени.

См. также функции DAY, MONTH, YEAR, HOUR, MINUTE, SECOND, DATE, DATE_FORMAT.

Синтаксис

SELECT EXTRACT(что_извлечь FROM дата) FROM имя_таблицы WHERE условие

Вместо ‘что_извлечь’ можно написать, к примеру, DAY — тогда из даты будет извлечен день, или, к примеру, YEAR — тогда будет извлечен год. Если же я напишу так:

YEAR_MONTH — то будет извлечен год и месяц (слитно, без разделителя).

Если вам нужно извлекать несколько частей не слитно, а используя разделитель — используйте DATE_FORMAT.

Форматы вывода, которые допустимо использовать (см. примеры для понимания):

Формат Что извлечется
SECONDсекунды
MINUTEминуты
HOURчасы
DAYдни
MONTHмесяцы
YEARгода
MINUTE_SECONDминуты и секунды слитно
HOUR_MINUTEчасы и минуты слитно
DAY_HOURдни и часы слитно
YEAR_MONTHгода и месяцы слитно
HOUR_SECONDчасы, минуты, секунды слитно
DAY_MINUTEдни, часы, минуты слитно
DAY_SECONDдни, часы, минуты, секунды слитно

Примеры

Все примеры будут по этой таблице workers, если не сказано иное:

id
айди
name
имя
date
дата рождения
1 Дима 1988-03-01
2 Петя 1989-04-02
3 Вася 1990-05-03

Пример

В данном примере из даты извлекается день месяца:

SELECT *, EXTRACT(DAY FROM date) as day FROM workers

SQL запрос выберет следующие строки:

id
айди
name
имя
date
дата рождения
day
день
1 Дима
1988-03-01
1
2 Петя 1989-04-02 2
3 Вася 1990-05-03 3

Пример

В данном примере из даты извлекается год:

SELECT *, EXTRACT(YEAR FROM date) as year FROM workers

SQL запрос выберет следующие строки:

id
айди
name
имя
date
дата рождения
year
год
1 Дима 1988-03-01 1988
2 Петя 1989-04-02 1989
3 Вася 1990-05-03 1990

Пример

В данном примере из даты извлекается год и месяц (слитно):

SELECT *, EXTRACT(YEAR_MONTH FROM date) as yearmonth FROM workers

SQL запрос выберет следующие строки:

id
айди
name
имя
date
дата рождения
yearmonth
год и месяц
1 Дима 1988-03-01 198803
2 Петя 1989-04-02 198904
3 Вася 1990-05-03 199005

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
Sub Вычленение_Max_даты()
    Dim i&, j%, k%, A, B, S$, Dt() As Date, MaxDt, D%, M%, Y%, U As Boolean, Mesyacy
    Mesyacy = Array("##", "январ", "феврал", "март", "апрел", "май", "июн", "июл", "август", "сентябр", "октябр", "ноябр", "декабр", "мая")
    A = ActiveSheet.
UsedRange.Value     For i = 1 To UBound(A)         B = A(i, 1)         B = Replace(B, ",", "|")         B = Replace(B, ";", "|")         B = Replace(B, ":", "|")         B = Replace(B, ". ", "|")         B = Replace(B, "-", "|")         B = Split(B, "|")         ReDim Dt(UBound(B))         For j = 0 To UBound(B)             U = True             S = LCase(B(j))             D = 0: M = 0: Y = 0             For k = 1 To Len(S) - 9                 If Mid(S, k, 10) Like "##.##.2###" Then                     Dt(j) = CDate(Mid(S, k, 10))                     U = False                     Exit For                 End If             Next k             If U Then                 For k = 1 To Len(S) - 6                     If Mid(S, k, 7) Like "##.2###" Then                         M = Val(Mid(S, k, 2))                         Y = Val(Mid(S, k + 3, 4))                         Exit For                     End If                 Next k                 If M = 0 Or Y = 0 Then                     For k = 1 To UBound(Mesyacy)                         If InStr(1, S, Mesyacy(k)) > 0 Then                             M = k                             If M = 13 Then M = 5                             Exit For                         End If                     Next k                     For k = 1 To Len(S) - 3                         If Mid(S, k, 5) Like " 20##" Then                             Y = Val(Trim(Mid(S, k, 5)))                             Exit For                         End If                     Next k                 End If                 If Left(S, 3) Like "## " Then                     D = Val(Left(S, 2))                 ElseIf Right(S, 3) Like " ##" Then                     D = Val(Right(S, 2))                 ElseIf Left(S, 2) Like "# " Then                     D = Val(Left(S, 1))                 ElseIf Right(S, 2) Like " #" Then                     D = Val(Right(S, 1))                 Else                     For k = 1 To Len(S) - 3                         If Mid(S, k, 10) Like "##.
##.2###" Then                             k = k + 9                         ElseIf Mid(S, k, 7) Like "##.2###" Then                             k = k + 6                         ElseIf Mid(S, k, 4) Like " ## " Then                             D = Val(Trim(Mid(S, k, 4)))                             Exit For                         ElseIf Mid(S, k, 3) Like " # " Then                             D = Val(Trim(Mid(S, k, 3)))                             Exit For                         End If                     Next k                 End If                 If D = 0 Then D = 25                 If D > 31 Then D = 1                 If M > 0 And Y > 0 Then Dt(j) = DateSerial(Y, M, D)              End If         Next j         MaxDt = Empty         For j = 0 To UBound(Dt)             If Dt(j) > MaxDt Then MaxDt = Dt(j)         Next j         Cells(i, 2) = MaxDt     Next i End Sub

MS SQL Дата только без времени

вопрос

Привет Всем,

у меня была некоторая путаница в течение некоторого времени с по существу настилом типа DateTime SQL с использованием T-SQL. По сути, я хочу взять значение DateTime скажем 2008-12-1 14:30:12 и сделать его 2008-12-1 00:00: 00. Многие запросы, которые мы запускаем для отчетов, используют значение даты в предложении WHERE, но у меня есть значение даты начала и конца дня и используется между, Или я нахожу какой-то другой метод.

В настоящее время я использую следующий: WHERE CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam

однако, это кажется немного неуклюжим. Я надеялся, что будет что-то более простое, как CAST([tstamp] AS DATE)

некоторые места в интернете рекомендуют использовать функцию DATEPART (), но затем я заканчиваю чем-то вроде этого:


WHERE DATEPART(year, [tstamp]) = DATEPART(year, @dateParam)
AND DATEPART(month, [tstamp]) = DATEPART(month, @dateParam)
AND DATEPART(day, [tstamp]) = DATEPART(day, @dateParam)

может быть, я слишком беспокоюсь о чем-то маленьком, и если да, пожалуйста, дайте мне знать.

Я просто хочу убедиться, что материал, который я пишу, максимально эффективен. Я хочу устранить всех слабых. связи.

какие предложения?

спасибо,
С

решение

спасибо всем за большую обратную связь. Много полезной информации. Я собираюсь изменить наши функции, чтобы исключить функцию с левой стороны оператора. Хотя большинство наших столбцов даты не используют индексы, это, вероятно, все еще лучшая практика.

это очень плохо для производительности, взгляните на Только В Базе Данных Вы Можете Получить 1000% + Улучшение, Изменив Несколько Строк Кода

функции на левой стороне оператора плохие

вот что вам нужно сделать

declare @d datetime
select @d =  '2008-12-1 14:30:12'

where tstamp >= dateadd(dd, datediff(dd, 0, @d)+0, 0)
and tstamp < dateadd(dd, datediff(dd, 0, @d)+1, 0)

запустите это, чтобы увидеть, что он делает

select dateadd(dd, datediff(dd, 0, getdate())+1, 0)
select dateadd(dd, datediff(dd, 0, getdate())+0, 0)

да, T-SQL может иногда чувствовать себя чрезвычайно примитивным, и именно такие вещи часто подталкивают меня к тому, чтобы делать много моей логики на моем языке выбора (например, C#).

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

взгляните на эту статью. Он предлагает довольно много удобных функций SQL по этим направлениям, которые, я думаю, помогут вы.

http://weblogs.sqlteam.com/jeffs/archive/2007/01/02/56079.aspx

осторожнее здесь, Если вы используете что-нибудь длинное строки WHERE CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam это заставит сканирование таблицы и индексы не будут использоваться для этой части.

гораздо более чистый способ сделать это-определить вычисляемый столбец

create table #t (
    d datetime, 

    d2 as 
        cast (datepart(year,d) as varchar(4)) + '-' +
        right('0' + cast (datepart(month,d) as varchar(2)),2) + '-' + 
        right('0' + cast (datepart(day,d) as varchar(2)),2) 
) 
-- notice a lot of care need to be taken to ensure the format is comparable.  (zero padding)

insert #t 
values (getdate())

create index idx on #t(d2)

select d2, count(d2) from #t 
where d2 between '2008-01-01' and '2009-01-22'
group by d2
-- index seek is used

таким образом, вы можете напрямую проверить столбец d2, и будет использоваться индекс, и вам не придется возиться с преобразованиями.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Theme: Overlay by Kaira Extra Text
Cape Town, South Africa