Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2010.08.27;
Скачать: CL | DM;

Вниз

Подскажите SQL запрос   Найти похожие ветки 

 
d@nger   (2010-04-25 09:41) [0]

Здравствуйте! Имеется таблица (Firebird) с полем дата, и идентификатор клиента.

id           org_id                date
1             231              01.03.2010
2             231              02.04.2010
3             231              07.04.2010
4             115              15.04.2010
5             115              17.04.2010
6             205              20.04.2010
7             205              02.05.2010
...


нужно выбрать все записи за определенный месяц. Это я конечно сделал, но теперь нужно выбрать последнюю по дате запись каждого клиента, т.е из приведенного примера должны остаться записи 3, 5, 6. Я конечно могу это сделать в цикле проверяя каждую запись, но это будет не так эффективно если бы это сделать с помощью запроса. Возможно ли сделать такой запрос?


 
_Юрий ©   (2010-04-25 09:52) [1]

передать требуемую дату параметром?

select * from table where date=:p


 
d@nger   (2010-04-25 10:01) [2]


> _Юрий ©   (25.04.10 09:52) [1]
>
> передать требуемую дату параметром?


дата не известна, известен месяц. Нужно вытащить все записи за этот месяц и среди этих записей оставить только уникальные организации с последней датой...
select * from table where (date>="01.04.2010")and(date<="30.04.2010") вот это все на что у меня ума хватило... как теперь убрать повторные организации с меньшими дататами, а оставить только одну с наибольшей датой...


 
sniknik ©   (2010-04-25 10:23) [3]

> только уникальные организации с последней датой...
+ GROUP BY
и Max


 
d@nger   (2010-04-25 10:24) [4]

Урраа! Получилось... погуглил в инете... вот мое решение:

select org_id, max(call_date) from call_log group by call_log.org_id


 
Anatoly Podgoretsky ©   (2010-04-25 10:44) [5]

> d@nger  (25.04.2010 10:01:02)  [2]

Последняя, она же наибольшая - это MAX естественно.


 
d@nger   (2010-04-25 10:49) [6]

теперь не могу объединить эти 2 запроса в один


select * from table where (date>="01.04.2010")and(date<="30.04.2010")


select org_id, max(call_date) from call_log group by call_log.org_id


пишу так:
select id,call_date from call_log where (call_date>="01.04.2010")and(call_date<="30.04.2010")and
(id in (select id, max(call_date) from call_log group by call_log.org_id))


ошибка

Invalid token.
Dynamic SQL Error.
SQL error code = -104.
Invalid command.
count of column list and variable list do not match.


как правильно его записать?


 
d@nger   (2010-04-25 11:30) [7]

я снова погуглил...  решение следующее...
select org_id, max(call_date) from call_log
group by org_id having (max(call_date)>="01.04.2010")and(max(call_date)<="30.04.2010")


 
sniknik ©   (2010-04-25 12:30) [8]

> select org_id, max(call_date) from call_log
> group by org_id having (max(call_date)>="01.04.2010")and(max(call_date)<="30.04.2010")

индекс по полю org_id или call_date есть? если только по call_date то решение очень глупое...  если есть и по org_id, то просто слегка "туповатое".
группировать по всей таблице например 10 миллионов записей. и после обрезать до 10 нужных, это не то же самое, что отобрать 1000 за месяц и после сгруппировать их в нужные 10...


 
d@nger   (2010-04-26 06:50) [9]

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


 
d@nger   (2010-04-26 07:09) [10]

может уважаемый админ перенесет мою тему в раздел баз данных?...
может кто нибудь подскажет что нибудь.. оптимально ли делать следующим образом
1) создавать сначала представление,
2) потом делать группировку в этом представлении,
3 )формировать отчет на основе полученных данных,
4) удалить представление

или все таки возможно как то обойтись без представления?


 
sniknik ©   (2010-04-26 07:44) [11]

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

p.s. самое место теме здесь. запросы с where описывают на втором, или третьем занятии в книгах типа "sql для чайников", сразу после введения... группировки попозже, но с ними у тебя проблем вроде нет.


 
d@nger   (2010-04-26 08:14) [12]

вымучил я все таки этот запрос...

select org_id, max(call_date) from call_log where call_date between "01.05.2010" and "30.05.2010"
group by org_id


всем спасибо, что направили на путь истинный.. ))))


 
Anatoly Podgoretsky ©   (2010-04-26 08:44) [13]


> может уважаемый админ перенесет мою тему в раздел баз данных?
> ...

С какой стати, твой вопрос вообще не имеет отношения к програмированию в Дельфи, тебе нужно в форум по FB, а здесь такого нет. Наиболее близкая конференция это Общая.


 
d@nger   (2010-04-26 09:03) [14]

придется мне опять поднять эту тему...

кроме полей org_id, и call_date? нужно вытащить еще 2 текстовых поля, но в этом случае скрипт не работает, НО если дабавить эти текстовые поля в group by, ошибки нет, но результат не группируется по org_id... как быть в этом случае?


 
sniknik ©   (2010-04-26 09:30) [15]

> но результат не группируется по org_id...
эк, я тебя "сглазил"...
> но с ними у тебя проблем вроде нет.

> как быть в этом случае?
читать четвертый раздел "sql для чайников" по "group by". и внимательно смотреть на call_date в запросе.


 
Дмитрий С ©   (2010-04-26 09:41) [16]

тут поможет уловка с CONCAT

SELECT * FROM `call_log` WHERE `id` IN (
   SELECT
       CAST(SUBSTRING(MAX(CONCAT(LPAD(`date`,20,0), `id`)), 21) AS INT)
   FROM
       `call_log`
   WHERE
       `date` between "01.05.2010" and "30.05.2010"
   GROUP BY `org_id`
)

Это на MYSQL. На FB переведешь сам


 
d@nger   (2010-04-26 10:42) [17]

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


 
d@nger   (2010-04-26 10:43) [18]

LPAD(`date`,20,0), `id`) может здесь нужнобыло использовать RPAD ?


 
test ©   (2010-04-26 11:08) [19]

ИМХО как то так.

select a.org_id, max(a.call_date) from call_log a
left join table b on ((date>="01.04.2010")and(date<="30.04.2010")) and a.org_id = b.id
group by a.org_id


 
sniknik ©   (2010-04-26 11:17) [20]

ужас какой...

простейший вариант это включить поля в агрегатных функциях, аналогично call_date (ведь он то тебе не мешает группировать по org_id)
но лучше конечно так (надеюсь id  это ключ, и авто инкремент (ну аналог его в FB), и еще надеюсь даты в строках воспринимаются правильно... хотя в любом случае советую параметры)

select org_id, call_date, еще 2 текстовых поля from call_log
WHERE id IN
(select max(id) from call_log where call_date between "01.05.2010" and "30.05.2010" group by org_id)


 
test ©   (2010-04-26 11:20) [21]

sniknik ©   (26.04.10 11:17) [20]
Oracle))


 
Дмитрий С ©   (2010-04-26 11:20) [22]


> sniknik ©

В условиях нет факта, что id и call_date одновременно возрастают.


 
boriskb ©   (2010-04-26 11:26) [23]

Самое время задуматься: "От инета больше вреда или пользы?"


 
d@nger   (2010-04-26 11:29) [24]


> test ©   (26.04.10 11:08) [19]
>
> ИМХО как то так.
>
> select a.org_id, max(a.call_date) from call_log a
> left join table b on ((date>="01.04.2010")and(date<="30.
> 04.2010")) and a.org_id = b.id
> group by a.org_id


этот вариант не дает доступа к тектовым полям таблицы call_log, в принципе он вообще ничем не отличается от моего варианта...


 
d@nger   (2010-04-26 11:31) [25]


> Дмитрий С ©   (26.04.10 11:20) [22]
>
>
> > sniknik ©
>
> В условиях нет факта, что id и call_date одновременно возрастают.
>


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


 
test ©   (2010-04-26 11:35) [26]

d@nger   (26.04.10 11:29) [24]
Какой доступ нужен?


 
d@nger   (2010-04-26 11:37) [27]

у меня такая мысль возникла, если группировка работает с агрегатными функциями, нельзя ли написать свою агрегатную функцию, которая ничего не делает, а возвращает то же значение что в него и посупило,  например: TXT("это текст") = это текст .... т.е сделав такю функцию мы сможем ее включить в параметры select и вывести отдельным столбцом


 
test ©   (2010-04-26 11:37) [28]

select c.* from call_log
left join
(select a.org_id, max(a.call_date) from call_log a
left join table b on ((date>="01.04.2010")and(date<="30.04.2010")) and a.org_id = b.id
group by a.org_id) b on c.id = b.id


 
test ©   (2010-04-26 11:39) [29]

d@nger   (26.04.10 11:37) [27]
Все уже украдено до нас))

select c.*, "это мы напишем тута","а это мы напишем в тама" from call_log с


 
d@nger   (2010-04-26 11:39) [30]


> test ©   (26.04.10 11:35) [26]
>
> d@nger   (26.04.10 11:29) [24]
> Какой доступ нужен?


помимо ORG_ID и CALL_DATE, есть текстовые поля ORG_NAME и TEXT, которые тоже нужно отобразить в результате запроса . если эти поля включить в select то придется и в группировку их включить, что повлияет на результат группировки


 
test ©   (2010-04-26 11:41) [31]

d@nger   (26.04.10 11:39) [30]
Проверь запрос из поста 28.


 
d@nger   (2010-04-26 11:45) [32]


> test ©   (26.04.10 11:41) [31]
>
> d@nger   (26.04.10 11:39) [30]
> Проверь запрос из поста 28.


проверяю....
select * from call_log c
left join
(select a.org_id, max(a.call_date) from call_log a
left join clients b on ((call_date>="01.04.2010")and(call_date<="30.04.2010")) and a.org_id = b.id
group by a.org_id) b on c.id = b.id


ошибка...
Invalid token.
Dynamic SQL Error.
SQL error code = -104.
Invalid command.
no column name specified for column number 2 in derived table B.


 
test ©   (2010-04-26 11:52) [33]

select * from call_log c
left join
(select a.org_id, max(a.call_date) max_date from call_log a
left join clients b on ((call_date>="01.04.2010")and(call_date<="30.04.2010")) and a.org_id = b.id
group by a.org_id) b on c.id = b.id


Ну назови поле как нибудь например max_date он же об этом говорит


 
d@nger   (2010-04-26 11:55) [34]


> Ну назови поле как нибудь например max_date он же об этом
> говорит

я не знаю куда его воткнуть... я sql плохо пока знаю


 
test ©   (2010-04-26 11:58) [35]

я привел же написал куда и где

select * from call_log c
left join
(select a.org_id, max(a.call_date) max_date from call_log a
left join clients b on ((call_date>="01.04.2010")and(call_date<="30.04.2010")) and a.org_id = b.id
group by a.org_id) b on c.id = b.id


 
d@nger   (2010-04-26 12:03) [36]

сорри.. не увидел...


 
d@nger   (2010-04-26 12:11) [37]

теперь другая ошибка ...
select * from call_log c
left join
(select a.org_id, max(a.call_date) max_date from call_log a
left join clients b on ((call_date>="01.04.2010")and(call_date<="30.04.2010")) and a.org_id = b.id
group by a.org_id) b on c.id = b.id


ошибка ...

> Column does not belong to referenced table.
> Dynamic SQL Error.
> SQL error code = -206.
> Column unknown.
> B.ID.
> At line 5, column 34.


 
sniknik ©   (2010-04-26 12:17) [38]

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


 
test ©   (2010-04-26 12:17) [39]

ошибка означает нет такого поля
скорее всего это он про
c.id = b.id
b.id должно быть b.org_id
c.id нужно смотреть в названиях полей таблицы

в select * from тожке лучше указать что тебе нужно select c.* from, а то он тебе весь набор вытащит.

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

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


 
d@nger   (2010-04-26 12:33) [40]

структура таблиц следующая:
таблица call_log
ID     - ключ
ORG_ID - ключ организации клиента из таблицы clients.id
CALL_DATE - дата
TEXT - текст
ORG_NAME - текст

в таблице clients много полей... но поле ID точно есть... тоже ключевое...



Страницы: 1 2 вся ветка

Текущий архив: 2010.08.27;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.07 c
15-1268215937
fford
2010-03-10 13:12
2010.08.27
подскажите компонент


11-1218719894
Дмитрий
2008-08-14 17:18
2010.08.27
Как узнать объем оперативной памяти


2-1267526403
Sairex
2010-03-02 13:40
2010.08.27
Как сравнить версии


15-1268404840
Илья_
2010-03-12 17:40
2010.08.27
Ошибка при отладке программы с помощью функции Trace into


2-1271858675
DROWSY
2010-04-21 18:04
2010.08.27
Компонент для выбора числового значения.