Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» SQL запрос

Автор: aidomars
Дата сообщения: 14.12.2011 16:20
Access 2003, имеем:
1 10.12.2011 18:00
Автор: dneprcomp
Дата сообщения: 14.12.2011 17:16
aidomars
Кстати, какой data type у [Дата] и [Время] ?
Если стринговый, то при большом количестве разнообразных дат и времени ни MAX, ни TOP не дадут верного результата. Нужен datetime.

http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
Автор: aidomars
Дата сообщения: 14.12.2011 19:00
dneprcomp
Тип все как положено, краткий формат даты и краткий формат времени. Ведь логически все правильно вычисляет, берет по каждому ID: максимум по Дате (то что требуется) и мах по времени (то что не требуется). Надо брать время в той же строке, что и дата. Вроде бы все просто, а не получается.
А вкратце задача такая. Пользователи заносят записи в базу, по каждой пишется дата и время записи, надо выбрать последние.
Автор: YuriyRR
Дата сообщения: 14.12.2011 20:26
aidomars
SELECT ID, Max(DT), Max(TM)
FROM ( SELECT ID,DT,(select MAX(TM) FROM T T2 WHERE t2.dt = t1.dt and t2.id = t1.id) as TM FROM T t1 ORDER BY 1)
GROUP BY ID ORDER BY 1;
Автор: aidomars
Дата сообщения: 14.12.2011 21:13
YuriyRR
У меня одна ж таблица.
Автор: dneprcomp
Дата сообщения: 14.12.2011 22:20
aidomars
Почитай по линку в моем предыдущем посте и станет понятно, что YuriyRR делает.
Там и другие варианты решения есть.

Цитата:
Тип все как положено, краткий формат даты и краткий формат времени

Если у обоих полей data type именно datetime, то какой смысел хранить раздельно?
Все равно внутреннее представление хранит и дату и время для обоих полей.
Места данные занимют одинаково.
Было бы одно поле datetime - дата и время вместе - все было бы гораздо проще.
Выборка бы производилась всего по двум полям простым
select ID,max([DateAndTime]) as Max_DateAndTime from table group by по ID
Потом уже можно парсить Max_DateAndTime как угодно.
А можно и сразу в select-e через функцию datepart
А с раздельным хранением только через sub select по методу YuriyRR
Автор: Jon_Dow
Дата сообщения: 14.12.2011 22:27
aidomars
Только связка сама на себя с подзапросом:
Код: SELECT T2.ID AS,T2.[Max-Дата] AS [Max-Дата],T1.[Время] AS [Время]
FROM
(SELECT table.ID AS ID,Max(table.[Дата]) AS [Max-Дата] FROM table GROUP BY table.ID) T1,
TABLE T2
WHERE
T2.ID=T1.ID AND T1.[Max-Дата]=T2.[Дата]
Автор: aidomars
Дата сообщения: 15.12.2011 05:52
dneprcomp
Да я уж думал про парсинг, видимо придется так и делать.
Jon_Dow
Сама на себя связка уж больно долго считает, а то и зависает. Сейчас попробую еще раз.
Автор: dneprcomp
Дата сообщения: 15.12.2011 06:10
aidomars

Цитата:
Да я уж думал про парсинг

И это наиболее правильный подход. Все что можно посчитать, хранится не должно.
Исключение составляют только такие данные, как финансовые исторические или нечто подобное.
Автор: aidomars
Дата сообщения: 15.12.2011 07:09
Все таки поэкспериментировал, вроде работает такой запрос. А так да, будет время, заменю на одно поле, пока таблицы не хочу трогать.

Код: SELECT T1.ID1, Max(T1.[Дата]) AS [Max-Дата], Last(T1.[Время]) AS [Last-Время]
FROM T1 AS T2 INNER JOIN T1 ON (T2.[Время] = T1.[Время]) AND (T2.[Дата] = T1.[Дата]) AND (T2.ID1 = T1.ID1)
WHERE (((T1.[Время])=[T2].[Время]) AND ((T2.[Дата])=[T1].[Дата]))
GROUP BY T1.ID1
ORDER BY T1.ID1, Max(T1.[Дата]);
Автор: Jon_Dow
Дата сообщения: 15.12.2011 08:10
aidomars
Ты считаешь что
Код: INNER JOIN
Автор: Czechoslovak
Дата сообщения: 15.12.2011 08:43

Цитата:
Тип все как положено, краткий формат даты и краткий формат времени. Ведь логически все правильно вычисляет, берет по каждому ID: максимум по Дате (то что требуется) и мах по времени (то что не требуется). Надо брать время в той же строке, что и дата. Вроде бы все просто, а не получается.
А вкратце задача такая. Пользователи заносят записи в базу, по каждой пишется дата и время записи, надо выбрать последние.


А что тут выбирать то. Примерно так

Код:
SELECT ID,Max(Data+Time)
FROM ТABLE
GROUP BY ID
Автор: aidomars
Дата сообщения: 15.12.2011 09:47
Jon_Dow
Кто ж спорил, просто в ходе экспериментов со связкой получались такие запросы, что вешали запрос, хотя он и исполнялся. Вот я и не хотел связу использовать. А сейчас вроде нормально работает.
Czechoslovak
Действительно просто, как бы обратный парсинг. Наверное его и буду выводить в итоговое представление даты и времени с соответствующими типами полей. Спасибо.
В итоге так и сделал, использовал Дата: Format([Дата_Время];"dd.mm.yyyy") и Время: Format([Дата_Время];"hh:mm")
Автор: Czechoslovak
Дата сообщения: 15.12.2011 10:57
aidomars
Че мудрить

Код:
SELECT ID,CDate(Int(Max(Data+Time))),CDate(Max(Data+Time) - Int(Max(Data+Time)))
FROM ТABLE
GROUP BY ID
Автор: aidomars
Дата сообщения: 15.12.2011 11:16
Czechoslovak
Да разницы тут никакой думаю, в запросе ли работать с датой, получая время и дату, или же выводить в итоговую форму через Format.
Автор: aidomars
Дата сообщения: 16.12.2011 14:06
Теперь другая проблема возникла: в столбец "Дата" выводятся значения из запроса., тут все гуд. В конструкторе: Format([Дата_Время];"dd.mm.yyyy"), тут немножко не гуд... Сортировка работает как со строками, т.е. по дате сортирует (01.12.2011, 02.10.2011, 03.12.2011 и т.д.). Если пишу в конструкторе Cdate(Format([Дата_Время];"dd.mm.yyyy")), то при сортировке ругается на пустые значения, т.к. не у всех стоит дата.
Как еще можно сделать, чтоб корректно сортировалось по дате?
Автор: Jon_Dow
Дата сообщения: 16.12.2011 15:25
aidomars
Не надо разводить пургу. Уточни какая конкретно структура таблицы у тебя имеется. Можно в формате CREATE TABLE... (Вариант со связкой таблицы самой на себя работает, а остальное - это все сильно зависимо от конкретной реализации таблицы).
Автор: aidomars
Дата сообщения: 16.12.2011 18:38
Вот сейчас набросал дома. Тоже самое. Проблема в том, что сортировка в Форме должна корректно работать если тип данных - дата. А в таблице "Главная" есть ID (3,5), у которых нет записей в "Дата записи". Соответсвенно в Форме дата у них пустая.
Вот и получается, что тип данных можно задать только в Форме.

http://rghost.ru/35064581

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

Код: IIf(IsNull([Дата_Время]), Null, CDate(Format([Дата_Время],"dd.mm.yyyy"))) AS дата
Автор: dneprcomp
Дата сообщения: 16.12.2011 22:44
aidomars

Цитата:
Вот и получается, что тип данных можно задать только в Форме

Сортировку надо делать не по полю 'Дата записи', а добавить в select вычисляемое поле 'DaysCount' и сортировать по этому полю.
В 'DaysCount' поместить DATEDIFF(day, '01/01/1900', [Дата записи])
Т.к. пустое поле = NULL то и представление NULL в datetime формате будет '01/01/1900'
Следовательно, у всех пустых полей разница равна 0
Автор: aidomars
Дата сообщения: 17.12.2011 08:52
dneprcomp
Так если сейчас уже сортировка работает, смысла нет добавлять вычисляемое поле.
Автор: dneprcomp
Дата сообщения: 17.12.2011 09:18
aidomars
А я и не говорю, что надо обязательно. Просто одно из возможных решений на сервере.
Автор: Unnicked
Дата сообщения: 18.05.2012 10:06
Есть следующая задача. Таблица состоит из трех столбцов - id, ptr и datetime.

Нужен запрос, который обновит столбец ptr, если он равен -1, записав в него значение ptr с тем же id, у которого максимальное datetime и который не равен -1.

Пожалуйста, помогите. Спасибо.
Автор: exteris
Дата сообщения: 18.05.2012 10:28
Unnicked
Как-то запутанно объяснили. Можете привести небольшой пример с данными и что хотите получить?
Автор: A_V
Дата сообщения: 18.05.2012 10:40
Unnicked
как-то так, если я правильно понял:

update t set t.ptr =
(
select t2.ptr
from t t2
where t2.id = t.id
and t2.datetime =
(select max(datetime)
from t t3
where t3.id = t2.id
and t3.ptr <> -1)
)
where t.ptr=-1

Автор: Unnicked
Дата сообщения: 18.05.2012 10:56
exteris
Было:

ptr id datetime
-1 4 12.05.2012 0:08:11
-1 4 29.04.2012 0:08:11
15 4 30.04.2012 0:08:11
17 4 14.04.2012 0:08:11
-1 3 17.04.2012 0:08:11
24 3 03.05.2012 0:08:11
12 3 04.05.2012 0:08:11

После запрос должно стать:

ptr id datetime
15 4 12.05.2012 0:08:11
15 4 29.04.2012 0:08:11
15 4 30.04.2012 0:08:11
17 4 14.04.2012 0:08:11
12 3 17.04.2012 0:08:11
24 3 03.05.2012 0:08:11
12 3 04.05.2012 0:08:11

A_V
Спасибо, все правильно поняли. Запрос работает, но выполняется долго - порядка 20 секунд (БД - Firebird, может в этом конечно проблема, но от нее отказаться нельзя...). В таблице порядка 2000 записей и всего 3 строки, в которых -1
Автор: exteris
Дата сообщения: 18.05.2012 11:39

Цитата:
Запрос работает, но выполняется долго - порядка 20 секунд

Индекс по ID поможет.
Автор: Unnicked
Дата сообщения: 18.05.2012 13:04
exteris, спасибо. Индекс помог
Автор: bandyn
Дата сообщения: 29.11.2013 08:29
ORACLE запрос:

select distinct
ENT.TITLE_SURNAME, ENT.NAME, ENT.OTCHESTVO, ENT.BIRTHDAY,
GUN.SERIES, GUN.NUMB, GUN.MAKE_YEAR,
CGUN.MODEL_TITLE, CGUN.CALIBR_CODE_1, CGUN.CALIBR_CODE_2, CGUN.CALIBR_CODE_3, CGUN.CALIBR_CODE_4,
CGUN.KINDGUN_CODE, CGUN.TYPE_GUN_CODE,
DOC.DOC_NAME||' '||DOC.DOC_SERIES||' '||DOC.DOC_NUMB||' от '||DOC.DOC_DATE as DOCS,
ENDS.END_DATE
from
ENT_PERSONS ENT,
DOC_RELATIONS SV,
GUN_GUNS GUN,
CODE_GUN CGUN,
DOC_DOCUMENTS_DOC_RELATIONS DRL,
DOC_DOCUMENTS DOC,
DOC_PERMISSIONS ENDS
where
ENT.TITLE_SURNAME='ФАМИЛИЯ' and ENT.NAME='ИМЯ' and ENT.OTCHESTVO='ОТЧЕСТВО' and ENT.BIRTHDAY='01.01.1985' and
ENT.ID=SV.EP_ID and SV.STATE=6 and SV.GUN_ID is not null and
SV.GUN_ID=GUN.ID and SV.ID=DRL.DRL_ID and DRL.DDC_ID=DOC.ID and ENDS.DDC_ID=DRL.DDC_ID and
CGUN.CODE=GUN.CODEGUN_CODE

1. Поле ENDS.END_DATE - Как вывести максимальную дату?
max(ENDS.END_DATE) over(partition by ENDS.END_DATE) - не помогает, выводит все даты
Автор: A_V
Дата сообщения: 29.11.2013 10:21
bandyn

Код:
select distinct
ENT.TITLE_SURNAME, ENT.NAME, ENT.OTCHESTVO, ENT.BIRTHDAY,
GUN.SERIES, GUN.NUMB, GUN.MAKE_YEAR,
CGUN.MODEL_TITLE, CGUN.CALIBR_CODE_1, CGUN.CALIBR_CODE_2, CGUN.CALIBR_CODE_3, CGUN.CALIBR_CODE_4,
CGUN.KINDGUN_CODE, CGUN.TYPE_GUN_CODE,
DOC.DOC_NAME||' '||DOC.DOC_SERIES||' '||DOC.DOC_NUMB||' от '||DOC.DOC_DATE as DOCS,
(SLECT MAX(ENDS.END_DATE) FROM DOC_PERMISSIONS ENDS WHERE ENDS.DDC_ID=DRL.DDC_ID)
from
ENT_PERSONS ENT,
DOC_RELATIONS SV,
GUN_GUNS GUN,
CODE_GUN CGUN,
DOC_DOCUMENTS_DOC_RELATIONS DRL,
DOC_DOCUMENTS DOC
where
ENT.TITLE_SURNAME='ФАМИЛИЯ' and ENT.NAME='ИМЯ' and ENT.OTCHESTVO='ОТЧЕСТВО' and ENT.BIRTHDAY='01.01.1985' and
ENT.ID=SV.EP_ID and SV.STATE=6 and SV.GUN_ID is not null and
SV.GUN_ID=GUN.ID and SV.ID=DRL.DRL_ID and DRL.DDC_ID=DOC.ID and
CGUN.CODE=GUN.CODEGUN_CODE
Автор: volser
Дата сообщения: 30.11.2013 13:30
bandyn
Лучше использовать явные джойны (лучше читать запрос)

Возможно так max(ENDS.END_DATE) over(partition by ENDS.DDC_ID)

Страницы: 1234567891011121314

Предыдущая тема: Строковый параметр в REG_BINARY


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.