SQL запрос

User avatar
GShapiev
Уже с Приветом
Posts: 2278
Joined: 02 Jan 2001 10:01
Location: MSK; NJ; MA; UAE, Chicago

Post by GShapiev »

Мне тут такое надо было сделать в MySQL.
Причем в версии без вложенных запросов.

Слабо? ;)
Гриша
------------
Why would anybody come here if they had a pony? Who leaves a country packed with ponies to come to a non-pony country? It doesn't make sense.. am I wrong?
User avatar
SVK
Уже с Приветом
Posts: 8255
Joined: 23 Jul 2003 03:53
Location: SPb - KW - NY - CT - MD

Post by SVK »

GShapiev wrote:Мне тут такое надо было сделать в MySQL.
Причем в версии без вложенных запросов.

Слабо? ;)

Ну, "охотничьи рассказы"? : :D

Было время, когда такие (и многие другие) вещи отлично делались на простых файлах... :mrgreen: :mrgreen: :mrgreen:

И главное - всё работало! :umnik1: :wink:
LG - Life's good.
But good life is much better.
NN13
Новичок
Posts: 53
Joined: 06 Apr 2004 20:09

Post by NN13 »

SVK wrote:
NN13 wrote:Я отметил в своем первом сообщении, что с id будет работать быстрее, если это identity field, а тогда оно упорядочено.

1) Identity зависит от реализации. Никто не гарантирует, что всегда будет по возрастанию. Это - как надеяться, что записи будут выданы по порядку даже без ORDER BY - "потому что они по порядку добавлялись". Иногда такое проходило...

2) Например в той же DB2 можно явно указать другой порядок генерации identity. Иногда нужно его менять, для оптимального partitioning, или еще зачем... Могут его поменять и при реорганизации базы, и много еще чего...

3) Ниоткуда также не следует, что записи а базу добавлялись в хронологическом порядке. Стоит только один раз добавить "вчерашнюю" запись, и вся та логика с ID может опять пойти насмарку

Не стоит программе выборки полагаться на ненужные предположения... Рано или поздно это "вдруг" перестанет работать :nono#:

NN13 wrote:А так:
select t1.* from mytable t1
inner join
(select max(time)as "time", convert(varchar(10), time, 101) as "day"
from mytable group by convert(varchar(10), time, 101)) t2
on t1.time=t2.time

дает как раз "последнюю запись для каждого (или нужного) значения в каждом дне".

По-моему, тут будет выдана "последняя запись за каждый день", без какой-либо связи с возможными значениями HouseID (или TEXT в моем примере). А нужно "последнюю в день для каждого HouseID"

А затем WHERE из примера в предыдущем посте просто отсеет те записи, где заданный HouseID не был последний за день? Или я чего-то не понимаю?

NN13 wrote:Я вот хотел спросить про DB2 - там такой оптимизатор умный, что можно позволить себе писать "where (...,...) in (...) вместо inner join?
Для MS SQL это определенно не пройдет.

Не во всех версиях DB2 это работало.
В принципе, если не работает, то это тоже заменить на JOIN по двум ключам...


В MS SQL identity всегда увеличивается (даже если вставлять "вчерашнюю" запись), но использовать его имеет смысл только если datetime работает медленно.

с Homeid все просто:

select t1.* from mytable t1
inner join
(select max(time)as "time", convert(varchar(10), time, 101) as "day"
from mytable
where homeid=...
group by convert(varchar(10), time, 101)) t2
on t1.time=t2.time
where homeid=...

Я похоже пропустил одно where раньше, my bad.
But I don't see any sense in providing a sql statements to a person, who can't fix a syntax error or add a filter condition. It can harm more then help.
User avatar
SVK
Уже с Приветом
Posts: 8255
Joined: 23 Jul 2003 03:53
Location: SPb - KW - NY - CT - MD

Post by SVK »

NN13 wrote:В MS SQL identity всегда увеличивается (даже если вставлять "вчерашнюю" запись), но использовать его имеет смысл только если datetime работает медленно.

Вернемся к нашим баранам. Пусть было сначала:

Code: Select all

100   2000-01-01-11:00:00  House1
200   2000-01-01-12:00:00  House1
300   2000-01-01-13:00:00  House1
400   2000-01-01-14:00:00  House1
500   2000-01-01-15:00:00  House1


Назавтра добавили еще (с возрастаюшим Identity):

Code: Select all

 800   2000-01-02-11:30:00  House1
 900   2000-01-02-12:30:00  House1
1000   2000-01-01-12:30:00  House1
1100   2000-01-01-11:30:00  House1


Ну, и что выдаст отбор по max(ID) за 2000-01-01 ???
LG - Life's good.
But good life is much better.
User avatar
Uzito
Уже с Приветом
Posts: 8239
Joined: 06 Feb 2002 10:01
Location: NJ, USA

Re: SQL запрос

Post by Uzito »

shadow7256 wrote:Есть таблица
мне надо выбрать последнюю запись из каждого дня. То есть результатом выборки будут записи с id равными 2,4 и 5
Как такое написать?


select *
from table
where id in (
select max(id) id
from table
group by trim(date)
)
order by id

Чего тут писать-то? ;)
User avatar
SVK
Уже с Приветом
Posts: 8255
Joined: 23 Jul 2003 03:53
Location: SPb - KW - NY - CT - MD

Post by SVK »

Это такая эпидемия - считать Identity эквивалентом для времени?

Есть 100 примеров, когда это не работает. Или перестанет работать от малейшего чиха. И можно найти еще 1000 примеров.
LG - Life's good.
But good life is much better.
shadow7256
Уже с Приветом
Posts: 9402
Joined: 18 Mar 2004 15:11
Location: New York -> FL

Post by shadow7256 »

да писать то и нечего.. не работает запрос этот как надо. Где Дима то? Или Тенгиз? По моему только они помогут :cry:
User avatar
Kotkov
Уже с Приветом
Posts: 342
Joined: 13 Mar 2002 10:01
Location: California

Post by Kotkov »

Privet!
А вот такое подойдет:
select * from TABLE
where TABLE.TIMEFIELD in (
select max(TIMEFIELD) from TABLE
group by trunc(TIMEFIELD))
Кто ищет, тот всегда найдет.
Живи своим умом, Пчёла! ©
User avatar
SVK
Уже с Приветом
Posts: 8255
Joined: 23 Jul 2003 03:53
Location: SPb - KW - NY - CT - MD

Post by SVK »

kotkov wrote:Privet!
А вот такое подойдет:
select * from TABLE
where TABLE.TIMEFIELD in (
select max(TIMEFIELD) from TABLE
group by trunc(TIMEFIELD))


GROUP BY <expression> мало где реализовано? У меня навскидку таких нет.
LG - Life's good.
But good life is much better.
User avatar
SVK
Уже с Приветом
Posts: 8255
Joined: 23 Jul 2003 03:53
Location: SPb - KW - NY - CT - MD

Post by SVK »

shadow7256 wrote:да писать то и нечего.. не работает запрос этот как надо.

Хорошо бы перевести это на русский язык.

Лично я скопировал в форум реальный результат из реальной базы. Все реально работало.

Если есть особенности в переделке его для MS SQL, то надо привести здесь проблему, тогда можно что-то понять.
LG - Life's good.
But good life is much better.
User avatar
GShapiev
Уже с Приветом
Posts: 2278
Joined: 02 Jan 2001 10:01
Location: MSK; NJ; MA; UAE, Chicago

Post by GShapiev »

Code: Select all

id   date   house
1   7/4/2004 3:23:00 PM   h1
10   7/4/2004 3:23:00 PM   h1
11   7/5/2004 3:24:00 PM   h1
12   7/5/2004 3:24:00 PM   h2
13   7/5/2004 3:24:00 PM   h2
14   7/5/2004 3:24:00 PM   h2
15   7/5/2004 3:24:00 PM   h2
16   7/5/2004 3:24:01 PM   h1
17   7/5/2004 3:24:00 PM   h1
18   7/5/2004 3:24:00 PM   h2
19   7/5/2004 3:34:00 PM   h2
2   7/4/2004 3:26:00 PM   h1
20   7/5/2004 3:15:00 PM   h2
21   7/5/2004 3:20:00 PM   h1
22   7/5/2004 3:24:00 PM   h1
3   7/4/2004 3:23:00 PM   h2
4   7/4/2004 3:23:00 PM   h2
5   7/4/2004 3:25:00 PM   h2
6   7/4/2004 3:23:00 PM   h1
7   7/4/2004 3:23:00 PM   h1
8   7/4/2004 3:23:00 PM   h1
9   7/4/2004 3:23:00 PM   h1


Вот этот запрос

Code: Select all

SELECT test.id, test.date,  test.house 
FROM test INNER JOIN test AS t2 ON datevalue(test.date) = datevalue(t2.date) and test.house = t2.house
GROUP BY test.id, test.date,  test.house
having test.date = max(t2.date)
order by test.date

Вместо datevalue подставляется фунция возвращающая дату

возвращает вот это

Code: Select all

id   date   house
5   7/4/2004 3:25:00 PM   h2
2   7/4/2004 3:26:00 PM   h1
16   7/5/2004 3:24:01 PM   h1
19   7/5/2004 3:34:00 PM   h2


P.S. Сделал небольшую поправку. Забыл про дома
Last edited by GShapiev on 05 Aug 2004 20:46, edited 1 time in total.
Гриша
------------
Why would anybody come here if they had a pony? Who leaves a country packed with ponies to come to a non-pony country? It doesn't make sense.. am I wrong?
User avatar
GShapiev
Уже с Приветом
Posts: 2278
Joined: 02 Jan 2001 10:01
Location: MSK; NJ; MA; UAE, Chicago

Post by GShapiev »

SVK wrote:
GShapiev wrote:Мне тут такое надо было сделать в MySQL.
Причем в версии без вложенных запросов.

Слабо? ;)

Ну, "охотничьи рассказы"? : :D


см. пост выше.
Правда для Access-а :mrgreen:
Гриша
------------
Why would anybody come here if they had a pony? Who leaves a country packed with ponies to come to a non-pony country? It doesn't make sense.. am I wrong?
User avatar
Kotkov
Уже с Приветом
Posts: 342
Joined: 13 Mar 2002 10:01
Location: California

Post by Kotkov »

SVK wrote:
kotkov wrote:select * from TABLE
where TABLE.TIMEFIELD in (
select max(TIMEFIELD) from TABLE
group by trunc(TIMEFIELD))

GROUP BY <expression> мало где реализовано? У меня навскидку таких нет.

Честно говоря, я мало представляю базу, в которой не релизовано GROUP BY <expression>.
Другое дело, что <expression> бывает разный в зависимости от БД. Так при задавании технического вопроса неплохо было бы написать тип сервера БД, ОС и т.д.
В данном случае <expression>=trunc() [Oracle DB]='выделение даты из поля дата-время'.
Кто ищет, тот всегда найдет.
Живи своим умом, Пчёла! ©
NN13
Новичок
Posts: 53
Joined: 06 Apr 2004 20:09

Post by NN13 »

To shadow7256:
shadow7256 wrote:да писать то и нечего.. не работает запрос этот как надо. Где Дима то? Или Тенгиз? По моему только они помогут :cry:


Я не поленился сотздать таблицу и проверить - все работает. Остальное - Ваши проблемы.

CREATE TABLE [dbo].[mytable] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[time] [datetime] NULL ,
[homeid] [char] (10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]

select t1.* from mytable t1
inner join
(select max(time)as "time", convert(varchar(10), time, 101) as "day"
from mytable t1
where homeid='a'
group by convert(varchar(10), time, 101)) t2
on t1.time=t2.time
where homeid='a'
order by "day"

To SVK:
Я полностью согласен с Вами по поводу id. Ограниченность применения identity столь велика, что не имеет смысл тратить время на поиск ситуаций, когда его можно было бы использовать (в данном случае как join condition, все больше не буду :)).
Ваш вариант не работает на MS SQL, потому что он не поддерживает сравнения 2 полей сразу - нужно заменить
where (TEXT, TIMES) in (
select T.TEXT, max(T.TIMES)
на что-нибудь вроде
where
TEXT+ convert(varchar(32), TIMES, 21) in (
select T.TEXT+ convert(varchar(32), max(T.TIMES), 21)
При этом он возвращает тот же результат, что и мой.
На этом все, работать надо. Всем спасибо.
User avatar
katit
Уже с Приветом
Posts: 23804
Joined: 05 Jul 2003 22:34
Location: Брест -> St. Louis, MO

Post by katit »

Короче. У товарища стопудово идет последовательное заполнение, т.е. выборка максимального id для каждого дня даст тот результат.

SQL Server:

Code: Select all

if exists (select * from dbo.sysobjects where id = object_id(N'[ttest]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [ttest]
GO
CREATE TABLE [ttest] (
   [ID] [int] NOT NULL ,
   [time] [datetime] NOT NULL
) ON [PRIMARY]
GO

insert ttest ([id], [time]) values (1, '2004-10-07 1:10')
insert ttest ([id], [time]) values (2, '2004-10-07 23:10')
insert ttest ([id], [time]) values (3, '2004-10-08 16:15')
insert ttest ([id], [time]) values (4, '2004-10-08 17:15')
insert ttest ([id], [time]) values (5, '2004-10-09 10:00')

select * from ttest

select max([id])
from ttest
group by CONVERT(Char(10), [time], 101)

Return to “Вопросы и новости IT”