Sql запрос выборка по дате

Sql запрос выборка по дате

Имеется таблица (STRZAP) вида:
ind1 — идентификатор
PCH_NAME — назвние части
DAT — дата/время ввода
и ряд других полей

т.е.:
ind1 PCH_NAME DAT
——- ———— ——————- .
11 ПЧ-1 24.06.2008 12:49:00 .
6 ПЧ-1 24.06.2008 12:51:46 .
12 ПЧ-2 24.06.2008 13:12:25 .
13 ПЧ-2 24.06.2008 13:12:29 .

Нужно получить набор данных в котором будут записи,
введенные каждой частью последними (в этот же день)

Для приведенного фрагмента:

ind1 PCH_NAME DAT
——- ———— ——————- .
6 ПЧ-1 24.06.2008 12:51:46 .
13 ПЧ-2 24.06.2008 13:12:29 .

Так как же получить такой НД?

SELECT PCH_NAME, max(DAT) as LastEntered
FROM STRZAP
WHERE
(
DAY(DAT)=DAY(GETDATE()) AND
MONTH(DAT)=MONTH(GETDATE()) AND
YEAR(DAT)=YEAR(GETDATE())
)
group by PCH_NAME

Этот код позволяет получить НД с полями времени
и названия части, а как полчить другие поля
соответсвующие этим записям?


stas © ( 2008-06-24 13:46 ) [1]

еще раз присоединить эту таблицу по дате и ID


stas © ( 2008-06-24 13:49 ) [2]

Ну или так (для MSSQL)
SELECT * FROM STRZAP
WHERE ind1= (select top 1 ind1 from STRZAP AS S
where S.PCH_NAME=STRZAP.PCH_NAME order by dat desc)


Kostafey © ( 2008-06-24 13:50 ) [3]

> еще раз присоединить эту таблицу по дате и ID

Так id в запросе

> SELECT PCH_NAME, max(DAT) as LastEntered
> FROM STRZAP
> WHERE
> (
> DAY(DAT)=DAY(GETDATE()) AND
> MONTH(DAT)=MONTH(GETDATE()) AND
> YEAR(DAT)=YEAR(GETDATE())
> )
> group by PCH_NAME

нет. Есть только название части и время.


Kostafey © ( 2008-06-24 13:51 ) [4]


Sergey13 © ( 2008-06-24 14:10 ) [5]

> [2] stas © (24.06.08 13:49)

SELECT * FROM STRZAP
WHERE dat= (select max(dat) from STRZAP AS S
where S.PCH_NAME=STRZAP.PCH_NAME)

а если другие поля в выборке не нужны, то просто

select PCH_NAME,max(dat) from STRZAP AS S
group by 1


stas © ( 2008-06-24 14:17 ) [6]

SELECT * FROM STRZAP
WHERE dat= (select max(dat) from STRZAP AS S
where S.PCH_NAME=STRZAP.PCH_NAME)

Если даты одинаковые, то будет двоить и т.д.


Павел Калугин © ( 2008-06-24 14:53 ) [7]


> stas © (24.06.08 14:17) [6]

цель этого запроса выбрать все за конкретную дату (в данном случае последнюю) . И что там будет "удвоено"?


Johnmen © ( 2008-06-24 14:56 ) [8]


> stas © (24.06.08 14:17) [6]
> Если даты одинаковые, то будет двоить

И чему это противоречит?

> и т.д.

Что конкретно т.д.?


stas © ( 2008-06-24 15:02 ) [9]

Павел Калугин © (24.06.08 14:53) [7]
ну если так, то да.
Johnmen © (24.06.08 14:56) [8]
троить, четверить. 🙂


stas © ( 2008-06-24 15:08 ) [10]

Павел Калугин © (24.06.08 14:53) [7]
Дело в том что приведеный запрос возвращает именно по одной записи
на каждую PCH_NAME, исходя из этого и был написан мой запрос.

SELECT PCH_NAME, max(DAT) as LastEntered
FROM STRZAP
WHERE
(
DAY(DAT)=DAY(GETDATE()) AND
MONTH(DAT)=MONTH(GETDATE()) AND
YEAR(DAT)=YEAR(GETDATE())
)
group by PCH_NAME


Johnmen © ( 2008-06-24 16:32 ) [11]


> stas © (24.06.08 15:02) [9]
> троить, четверить. 🙂

Так чему же это противоречит?

> Дело в том что приведеный запрос возвращает именно по одной записи
> на каждую PCH_NAME, исходя из этого и был написан мой запрос.

Твой запрос неверный даже в рамках формальной логики. Ибо "последних" записей м.б. больше одной.


stas © ( 2008-06-24 16:38 ) [12]

>Так чему же это противоречит?
не чему. Смотря что автору темы нужно.


Johnmen © ( 2008-06-24 16:44 ) [13]


stas © ( 2008-06-24 16:49 ) [14]

Johnmen © (24.06.08 16:44) [13]
если быть точным [5].
[2] будет эффективным, при наличии дополнительных условий сортировки.


Johnmen © ( 2008-06-24 17:11 ) [15]


> stas © (24.06.08 16:49) [14]
> если быть точным [5].

Я точен. Т.о. [6]

> [2] будет эффективным, .

Что такое "эффективным"? Как это измерено? И по сравнению с чем?


stas © ( 2008-06-24 17:19 ) [16]

в [6] это я продублировал запрос из [5].
по сравнению с 6 или 5 — как удобнее.
Измерять ненужно.


Johnmen © ( 2008-06-24 17:26 ) [17]


> в [6] это я продублировал запрос из [5].

Я спрашивал про слова, которые ты там написал. Если не доходит.

> Измерять ненужно.

Тебе было откровение?
Знаешь, у меня они тоже бывают. Так вот моё откровение говорит, что не будет.


stas © ( 2008-06-24 17:26 ) [18]

Просто немного усложним задачу, добавим еще поле dat2.
И нам нужно будет получить поля записи, которая соответсвует мимимальному dat2 при максимальном dat, на каждый PCH_NAME
(ого завернул)
В запросе [2] мы просто dat2 добавляем к условию сортировки.
А как быть с запросом [5] ?
(я конечно незнаю мож есть какие-то решения пока я считаю самым простым [2])


Павел Калугин © ( 2008-06-24 17:32 ) [19]


> stas © (24.06.08 15:08) [10]

Данный запрос вернет последнюю запись по каждой части в текущую дату.
А теперь что делать если такое надо за каждый день строить? То есть следующий вопрос ожидаем
как посмотреть какую запись какая часть вводила последней за 3-й квартал минувшего года?
запрос в [6] модифицируется в два притопа три прихлопа.
Опять же, надо учитывать скорость поступления данных. Если данные поступают чаще чем раз в милисекунду то таки да, надо изобретать (точнее приписывать дистинкт). Но при таком количестве данных в день (скорость поступления данных сравнима с милисекундой), я думаю, тут раньше вопросы о "тормозах" появились бы.


stas © ( 2008-06-24 17:32 ) [20]

Читайте также:  Как понять что твой телефон заблокировали

Johnmen © (24.06.08 17:26) [17]
>Надеюсь что твое откровение тебя не подведет.


Павел Калугин © ( 2008-06-24 17:34 ) [21]

опять же исхожу из того что "другие данные нужны" то есть не только часть и дата а например id последней записи


stas © ( 2008-06-24 17:35 ) [22]

Павел Калугин © (24.06.08 17:32) [19]

В чем сложность?

declare @dat datetime

SELECT * FROM STRZAP
WHERE ind1= (select top 1 ind1 from STRZAP AS S
where S.PCH_NAME=STRZAP.PCH_NAME
AND dat


Павел Калугин © ( 2008-06-24 17:38 ) [23]

хе.
1. речь про сложности с запросом в [10]
2. и получим последнюю запись в квартале а не за каждый день квартала.


stas © ( 2008-06-24 17:46 ) [24]

Павел Калугин © (24.06.08 17:38) [23]
Че-то непонял, ладно я ухожу с дома напишу.
А что в 10? это не мой запрос, это автора.
Вопрос не втом что прав кто-то или нет, хочется рассмотреть эту темы что же действительно правильно, я пока все же настаиваю на мной приведенном запросе.


Павел Калугин © ( 2008-06-24 18:26 ) [25]

в [6] приведен идеологически верный запрос
SELECT *
FROM STRZAP
WHERE dat= (select max(dat)
from STRZAP AS S
where S.PCH_NAME=STRZAP.PCH_NAME
)

то есть, получить все записи соответствующие условию.
Далее про "дублирование"
В каком темпе должны вводится данные что в одну милисекунду появится 2 записи? Сколько запсей будет в таблице через полгода?


Anatoly Podgoretsky © ( 2008-06-24 20:00 ) [26]

> Павел Калугин (24.06.2008 17:32:19) [19]

При такой скорости поступления данных вопрос врядли здесь появится, но конечно бывают исключения.


Anatoly Podgoretsky © ( 2008-06-24 20:03 ) [27]


> В каком темпе должны вводится данные что в одну милисекунду
> появится 2 записи? Сколько запсей будет в таблице через
> полгода?

А почему в одну миллисекунду, разве СУБД была озвучена.


stas © ( 2008-06-24 22:58 ) [28]

Павел Калугин © (24.06.08 18:26) [25]
Элементарно — пакетная вставка, автоматизированная т.е. цикл либо прибор регистрации данных
Да я вобщем согласился ([14]) что в конкретном примере , будет достаточно [6]. В конце концов на поле с датой+PCH_NAME можно повесить уникальный индекс.
Хотя в самом начале я написал объеденить запрос с этой же таблицей т.е. [6]
Интересно что же на самом деле устроило автора.
и что по поводу — stas © (24.06.08 17:26) [18]?


Kostafey © ( 2008-06-25 01:25 ) [29]

> [6] stas © (24.06.08 14:17)
> SELECT * FROM STRZAP
> WHERE dat= (select max(dat) from STRZAP AS S
> where S.PCH_NAME=STRZAP.PCH_NAME)
>
> Если даты одинаковые, то будет двоить и т.д.

Согласен. Теоретически возможно.
Хотя практически нет. Т.к. сведения по каждой
части вносятся диспетчерами раз в сутки,
но в течение суток могут корректироваться,
отсюда и требование к тому что должна быть
последняя запись. Конечно 2 записи 1 диспетчер
за тысячную секунды не внесет, а вот запросом
на insert сделать это можно.

Поэтому
[2] stas © (24.06.08 13:49)
лучше.


> [11] Johnmen © (24.06.08 16:32)
>
> > stas © (24.06.08 15:02) [9]
> > троить, четверить. 🙂
>
> Так чему же это противоречит?
>
> > Дело в том что приведеный запрос возвращает именно по
> одной записи
> > на каждую PCH_NAME, исходя из этого и был написан мой
> запрос.
>
> Твой запрос неверный даже в рамках формальной логики. Ибо
> "последних" записей м.б. больше одной.

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


> [18] stas © (24.06.08 17:26)

Расширять зарос не планируется.
знаю, все вначале так же говорят 🙂


> [27] Anatoly Podgoretsky © (24.06.08 20:03)
> А почему в одну миллисекунду, разве СУБД была озвучена.

О, виноват. MS SQL Server 2000.

Да, и нужно не забывать, что, возможно,
диспетчер еще не вводил данные сегодня,
поэтому в итоге:

SELECT * FROM STRZAP
WHERE ind1=
(
select top 1 ind1 from STRZAP AS S
where
(S.PCH_NAME=STRZAP.PCH_NAME)
and
(
DAY(DAT)=DAY(GETDATE()) AND
MONTH(DAT)=MONTH(GETDATE()) AND
YEAR(DAT)=YEAR(GETDATE())
)
order by dat desc
)


Johnmen © ( 2008-06-25 10:00 ) [30]


> Если это произойдет. хотя практически врядли,
> то в результирующем наборе данных будет одна запись

И это неверно. Что я и пытался безуспешно втолковать кое-кому.
А уж если принять за аксиому "практически врядли", то запрос [6] правильнее во всех смыслах.


Kostafey © ( 2008-06-25 10:22 ) [31]

> А уж если принять за аксиому "практически врядли", то запрос
> [6] правильнее во всех смыслах.

Правильнее почему?

Система имеет не только пользователей, но
и администраторов, квалификация которых
варьируется в широком диапазоне :),
так что хотелось бы чтобы результат
запроса не шокировал (читай выдавал единственную
запись по каждой части) вне зависимости
от шаманства с БД.


stas © ( 2008-06-25 10:45 ) [32]

Johnmen © (25.06.08 10:00) [30]
и что по поводу — stas © (24.06.08 17:26) [18]?

Оператор языка SQL SELECT предназначен для запросов на выборку данных из базы данных. Он может быть использован как без условий (выбор всех строк во всех столбцах или всех строк в определённых столбцах), так и с многочисленными условиями (выбор определённых строк), которые заданы в секции WHERE. Ознакомимся со средствами SQL, которыми можно задавать эти условия на выборку данных, а также узнаем, как использовать оператор SELECT в подзапросах.

Читайте также:  Как правильно заряжать power bank xiaomi 10000

SELECT для выбора столбцов таблицы

Запрос с оператором SELECT для выбора всех столбцов таблицы имеет следующий синтаксис:

То есть для выбора всех столбцов таблицы после слова SELECT нужно ставить звёздочку.

Если вы хотите выполнить запросы к базе данных из этого урока на MS SQL Server, но эта СУБД не установлена на вашем компьютере, то ее можно установить, пользуясь инструкцией по этой ссылке.

Работать будем с базой данных фирмы — Company1. Скрипт для создания этой базы данных, её таблиц и заполения таблиц данными — в файле по этой ссылке.

Пример 1. Итак, есть база данных фирмы — Company1. В ней есть таблица Org (Структура фирмы) и Staff (Сотрудники). Требуется выбрать из таблиц все столбцы. Соответствующий запрос для выбора всех столбцов из таблицы Org выглядит следующим образом (на MS SQL Server — с предваряющей конструкцией USE company1;):

Этот запрос вернёт следующее (для увеличения картинки щёлкнуть по ней левой кнопкой мыши):

Запрос для выбора всех столбцов из таблицы Staff выглядит следующим образом (на MS SQL Server — с предваряющей конструкцией USE company1;):

Этот запрос вернёт следующее:

Для выбора определённых столбцов таблицы нам потребуется вместо звёздочки перечислить через запятую названия всех столбцов, которые требуется выбрать:

Пример 2. Пусть требуется из таблицы Org выбрать столбцы Depnumb и Deptname, в которых содержатся данные соответственно о номерах отделов фирмы и об их названиях. Запрос для получения такой выборки будет следующим (на MS SQL Server — с предваряющей конструкцией USE company1;):

А из таблицы Staff нужно выбрать столбцы Dept, Name, Job, в которых содержатся соответственно данные о номере отдела, в котором трудится сотрудник, его имени и должности (на MS SQL Server — с предваряющей конструкцией USE company1;):

SELECT и WHERE для выбора строк таблицы

Для выбора определённых строк таблицы вместе с оператором SELECT уже потребуется ключевое слово WHERE, указывающее на некоторое значение или несколько значений, содержащиеся в интересующих нас строках. Наиболее простые условия задаются при помощи операторов сравнения и равенства ( , =), а также ключевого слова IS. Условий может быть несколько, тогда они перечисляются с использованием ключевого слова AND. Запросы для выбора строк имеют следующий синтаксис:

Пример 3. Выберем из таблицы Staff строки, в которых содержатся данные только о сотрудниках, которые работают в 38-м отделе (на MS SQL Server — с предваряющей конструкцией USE company1;):

Этот запрос вернёт следующие данные:

Пример 4. В предыдущем примере мы выбирали строки из таблицы только по значению одного столбца — DEPT. Пусть теперь нужно выбрать данные о сотрудниках, которые работают в 38-м отделе и должность которых — служащий (Clerk). Для этого в секции WHERE соответствующие значения нужно перечислить с использованием слова AND (на MS SQL Server — с предваряющей конструкцией USE company1;):

Этот запрос вернёт следующие данные:

Пример 5. Пусть нужно выбрать из таблицы Staff идентификаторы и имена тех сотрудников, размер комиссии которых — неопределённый. Для этого в секции WHERE перед указанием значения столбца Comm — NULL нужно ставить не знак равенства, а слово IS (на MS SQL Server — с предваряющей конструкцией USE company1;):

Этот запрос вернёт следующие данные:

Для указания значений в строках, которые требуется выбрать, используются и знаки сравнения.

Пример 6. Выберем из таблицы имена, размеры заработные платы и число лет, проработанных в фирме, сотрудников, которые работают в фирме более девяти лет (на MS SQL Server — с предваряющей конструкцией USE company1;):

Запрос вернёт следующие строки:

Использование SELECT и предикатов IN, OR, BETWEEN, LIKE

Предикаты — слова IN, OR, BETWEEN, LIKE в секции WHERE — также позволяют выбрать определённые диапазоны значений (IN, OR, BETWEEN) или значения в строках (LIKE), которые требуется выбрать из таблицы. Запросы с предикатами IN, OR, BETWEEN имеют следующий синтаксис:

Запросы с предикатом LIKE имеют следующий синтаксис:

Пример 7. Пусть требуется выбрать из таблицы Staff имена, должности и число отработанных лет сотрудников, работающих в отделах с номерами 20 или 84. Это можно сделать следующим запросом (на MS SQL Server — с предваряющей конструкцией USE company1;):

Результат выполнения запроса:

На сайте есть подробный урок об использовании предиката IN.

Пример 8. Пусть теперь требуется выбрать из таблицы Staff те же данные, что и в предыдущем примере. Запрос со словом OR аналогичен запросу со словом IN и перечислением интересующих значений в скобках. Запрос будет следующим (на MS SQL Server — с предваряющей конструкцией USE company1;):

Пример 9. Выберем из той же таблицы имена, должности и число отработанных лет сотрудников, зарплата которых между 15000 и 17000 включительно (на MS SQL Server — с предваряющей конструкцией USE company1;):

Результат выполнения запроса:

На сайте есть подробный урок об использовании предиката BETWEEN.

Предикат LIKE используется для выборки тех строк, в значениях которых встречаются символы, указанные после предиката между апострофами (‘).

Пример 10. Выберем из той же таблицы имена, должности и число отработанных лет сотрудников, имена которых начинаются с буквы S и состоят из 7 символов (на MS SQL Server — с предваряющей конструкцией USE company1;):

Символ подчёркивания (_) означает любой символ. Результат выполнения запроса:

Пример 11. Выберем из той же таблицы имена, должности и число отработанных лет сотрудников, имена которых начинаются с буквы S и содержат любые другие буквы в любом количестве (на MS SQL Server — с предваряющей конструкцией USE company1;):

Читайте также:  Как переустановить медиаплеер на виндовс 7

Символ процентов (%) означает любое количество символов. Результат выполнения запроса:

На сайте есть подробный урок об использовании предиката LIKE.

Значения, указанные с использованием предикатов IN, OR, BETWEEN, LIKE можно инвертировать при помощи слова NOT. Тогда запрашиваемые данные будут иметь противоположный смысл. Если мы используем NOT IN (20, 84), то будут выведены данные сотрудников, которые работают во всех отделах, кроме имеющих номера 20 и 84. С использованием NOT BETWEEN 15000 AND 17000 можно получить данные сотрудников, зарплата которых не входит в интервал от 15000 до 17000. Запрос с NOT LIKE выведет данные сотрудников, чьи имена не начинаются или не содержат символов, указанных с NOT LIKE.

Написать SQL запросы с SELECT и предикатами IN, NOT IN, BETWEEN самостоятельно, а затем посмотреть решения

Есть база данных "Театр". Таблица Play содержит данные о постановках. Таблица Team — о ролях актёров. Таблица Actor — об актёрах. Таблица Director — о режиссёрах. Поля таблиц, первичные и внешние ключи можно увидеть на рисунке ниже (для увеличения нажать левой кнопкой мыши).

Пример 12. Вывести список актёров, которые не разу не были утверждены на главную роль. В таблице team данные о главных ролях содержатся в столбце mainteam. Если роль — главная, то в соответствующей строке отмечено ‘Y’.

Пример 13. Вывести список актеров, которые играли во всех спектаклях WilliamShakespeare. Данные об авторах содержается в таблице play в столбце author.

Пример 14. Вывести спектакли, в которых средний возраст актеров от 20 до 30 (использовать BETWEEN, Group by, Having, AVG, перекрестное соединение таблиц (CROSS JOIN), удобнее без слова JOIN, а с перечислением таблиц через запятую).

SELECT и ORDER BY — сортировка (упорядочение) строк

Разобранные до сих пор запросы SQL SELECT возвращали строки, которые могли быть расположены в любой последовательности. Однако часто требуется отсортировать строки по порядку номеров, алфавиту и другим признакам. Для этого служит ключевое словосочетание ORDER BY. Такие запросы имеют следующий синтаксис:

Пример 15. Вновь база данных Company1. Пусть требуетя выбрать из таблицы Staff сотрудников, работающих в отделе с номером 84 и отсортировать (упорядочить) записи по числу отработанных лет в возрастающем порядке (на MS SQL Server — с предваряющей конструкцией USE company1;):

Слово ASC указывает, что порядок сортировки — возрастающий. Это слово не обязательно, так как возрастающий порядок сортировки применяется по умолчанию. Результат выполнения запроса:

Пример 16. Пусть требуетя выбрать те же данные, что и в предыдущем примере, но отсортировать (упорядочить) записи по числу отработанных лет в убывающем порядке (на MS SQL Server — с предваряющей конструкцией USE company1;):

Слово DESC указывает, что порядок сортировки — убывающий. Результат выполнения запроса:

SELECT и DISTINCT — удаление дубликатов строк

Когда для значений строк таблицы не задано условие уникальности, в результатах запроса могут встретиться одинаковые строки. Часто требуется вывести лишь уникальные строки. Это делается при помощи выражения DISTINCT после оператора SELECT.

Пример 17. Пусть требуетcя узнать, какие существуют отделы и какие должности среди отделов, номера которых меньше 30. Это можно сделать при помощи следующего запроса (на MS SQL Server — с предваряющей конструкцией USE company1;):

Результат выполнения запроса:

Оператор SELECT в подзапросах SQL

До сих пор мы разбирали конструкции SQL с оператором SELECT, в которых условия, по котором выбираются данные, и сами выбираемые данные содержатся в одной и той же таблице базы данных. На практике часто бывает, что данные, которые надо выбрать, содержатся в одной таблице, а условия — в другой. Здесь на помощь приходят подзапросы: значения условия отбора возвращаются из другого запроса (вложенного запроса), начинающегося также с SELECT. Запросы с подзапросами могут выдавать как одну, так и несколько строк.

Пример 18. Все те же таблицы Org и Staff. Пусть требуетcя узнать, в каком подразделении работает сотрудник с идентификационным номером 16, и где это подразделение расположено. Но информация о подразделениях хранится в таблице Org, а информация о сотрудниках — в таблице Staff. Это можно сделать при помощи следующего запроса с подзапросом, в котором внешний SELECT обращается к таблице Org, а внутренний SELECT — к таблице Staff:

Пример 19. Пусть теперь требуетcя узнать, в каких подразделениях (без дублирования) работают сотрудники с заработной платой менее 13000. Для этого в секции WHERE внешнего SELECT (запрос к таблице Org) задаётся условие, принимающее диапазон значений (IN), а внутренний SELECT (к таблице Staff) как раз возвращает требуемый диапазон значений:

Имею таблицу вот такого вида:

Не могу сделать выборку по дате и времени. Делаю так:

Но выдаются значения только за последнюю дату.

Подскажите как правильней будет сделать запрос

1 ответ 1

Вам нужно выбирать по сумме даты и времени

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

Если же индекса по полю DateReaders нет, то и условие не нужно. В любом случае будет полный перебор записей

А вообще разделение полей даты и времени в 90% плохая архитектура. Если вам не нужны выборки за определенное время для каждого дня, то эти поля нужно объединить в одно поле типа TIMESTAMP

Ссылка на основную публикацию
Adblock detector