powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
18 сообщений из 18, страница 1 из 1
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35978714
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Превед!

Есть таблицы:

таб. Docs (Документы), поля:
DocID - ид записи в таблице
DocTypeID - ид типа дока
... и тд

таб. DocsTypes (виды документов), поля:
DocTypeID - ид записи в таблице
DocTypeName - наименование типа документа
...

таб. DocsStates (разновидности состояний документов), поля:
DocStateID - ид записи в таблице
DocStateName - наименование состояния
...

таб. DocsStatesLog (журнал состояний документов), поля:
RecID - ид записи в таблице
DocID - ид документа из таблицы Docs
DocStateID - ид состояния документа из DocsStates
DocStateDate - дата присвоения состояния
...

Поскольку в DocsStatesLog каждый раз при получении нового состояния вносится запись, то на один DocID может приходиться несколько записей об изменении состояния документа.
И если я сделаю такую выборку
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT
   Docs.DocID,;
   DocTypes.DocTypeName,;
   DocsStatesLog.DocStateID  ,;
   DocsStatesLog.DocStateDate ,;
   DocsStates.DocStateName;
FROM Docs;
  LEFT JOIN DocsTypes ON DocsTypes.DocTypeID = Docs.DocTypeID ;
  LEFT JOIN DocsStatesLog ON DocsStatesLog.DocID = Docs.DocID;
  LEFT JOIN DocsStates ON DocsStates.DocStateID  = DocsStatesLog.DocStateID;
INTO CURSOR curDocs  
то получу по несколько записей на каждый документ, а как сделать выборку чтобы в нее попало бы только текущее состояние каждого документа, т.е. последнее присвоенное и только?

спасибо.

вфп9
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35978788
ПД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
СТАС-КО, попробуйте навесить агрегатные ф-ции на
подчиненные таблы. Ну или условия добавьте- для этих джойнов чтоб
записи брались с наибольшими ID- шниками.
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35979293
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35979416
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВладимирМ Выбрать из дочерней таблицы записи с максимальной датой оба Ваши варианта (3й, экзотический - не пробовал) почему-то зацикливают mysql - он хавает 99% ресурсов сервера и не дает результата вообще... впрочем точно так же как и в моем примере, который я зачислил в неверные из-за того же зависания (по этой же причине собственно и задал свой вопрос):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
SELECT
   Docs.DocID,;
   DocTypes.DocTypeName,;
   DocsStatesLog.DocStateID  ,;
   DocsStatesLog.DocStateDate ,;
   DocsStates.DocStateName;
FROM Docs;
  LEFT JOIN DocsTypes ON DocsTypes.DocTypeID = Docs.DocTypeID ;
  LEFT JOIN DocsStatesLog ON DocsStatesLog.DocStateDate IN(;
SELECT MAX(DocStateDate) FROM DocsStatesLog WHERE DocsStatesLog.DocID = Docs.DocID);
  LEFT JOIN DocsStates ON DocsStates.DocStateID  = DocsStatesLog.DocStateID;
INTO CURSOR curDocs 
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35979452
piva
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mysql с подзапросами ваще как-то странно работает, особенно после того как избалует фокс - поэтому в таких случаях делю запрос не несколько - тогда работает быстро. А так он именно грузит сервер по самое "не балуй"
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35979929
Tohan_ORA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
CTAC-KO
таб. DocsStatesLog (журнал состояний документов), поля:
DocStateDate - дата присвоения состояния
как сделать выборку чтобы в нее попало бы только текущее состояние каждого документа, т.е. последнее присвоенное и только?

День добрый!
Если критерий последнего- дата присвоения состояния, то можно попробовать что-то вроде этого:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
SELECT  d.DocID,a.DocTypeName,b.DocStateID,b.DocStateDate,c.DocStateName;
FROM Docs d;
LEFT JOIN DocsTypes a ON a.DocTypeID = d.DocTypeID ;
LEFT JOIN DocsStatesLog b ON b.DocID = d.DocID;
LEFT JOIN DocsStates c ON c.DocStateID  = b.DocStateID;
where b.DocStateDate=(select top  1  DocStateDate from DocsStatesLog where DocID=d.DocID);
or b.DocStateDate is null
или
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
SELECT  d.DocID,a.DocTypeName,b.DocStateID,b.DocStateDate,c.DocStateName;
FROM Docs d;
LEFT JOIN DocsTypes a ON a.DocTypeID = d.DocTypeID ;
LEFT JOIN DocsStatesLog b ON b.DocID = d.DocID;
LEFT JOIN DocsStates c ON c.DocStateID  = b.DocStateID;
where b.DocStateDate = (select max(DocStateDate) from DocsStatesLog where DocID=d.DocID)
or b.DocStateDate is null
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35979937
Tohan_ORA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В случае Top-a уточнение:
[src]SELECT d.DocID,a.DocTypeName,b.DocStateID,b.DocStateDate,c.DocStateName;
FROM Docs d;
LEFT JOIN DocsTypes a ON a.DocTypeID = d.DocTypeID ;
LEFT JOIN DocsStatesLog b ON b.DocID = d.DocID;
LEFT JOIN DocsStates c ON c.DocStateID = b.DocStateID;
where b.DocStateDate=(select top 1 DocStateDate from DocsStatesLog where DocID=d.DocID order by DocStateDate desc);
or b.DocStateDate is null
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35981505
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2Tohan_ORA - Ваш пример тоже "опустил" мускул - безрезультатный висняк... А select top 1 там ваще не канает.
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35981637
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что же вы все так MAX() любите? Там же другой вариант показан

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
SELECT
	Docs.DocID, ;
	DocTypes.DocTypeName, ;
	DocsStatesLog.DocStateID, ;
	DocsStatesLog.DocStateDate , ;
	DocsStates.DocStateName ;
FROM Docs ;
INNER JOIN DocsTypes ON DocsTypes.DocTypeID = Docs.DocTypeID ;
INNER JOIN DocsStatesLog as dsl ON dsl.DocId = Docs.DocId ;
INNER JOIN DocsStates ON DocsStates.DocStateID  = dsl.DocStateID ;
WHERE 	NOT EXISTS(select 'x' from DocsStatesLog ;
		where DocsStatesLog.DocId = dsl.DocId ;
			and DocsStatesLog.DocStateDate > dsl.DocStateDate) ;
	AND ;
	NOT EXISTS(select 'x' from DocsStatesLog ;
		where DocsStatesLog.DocId = dsl.DocId ;
			and DocsStatesLog.DocStateDate = dsl.DocStateDate ;
			and DocsStatesLog.RecId > dsl.RecId) ;
INTO CURSOR curDocs 

Все дело в подзапросе по NOT EXISTS(), который отсекает записи лога с тем же номером документа, но с датой меньше, чем у текущей записи.

Второй подзапрос с условием по RecId нужно только в том случае, если в логе могут быть записи с одинаковым значением даты для одного документа. При этом я предполагаю, что записи лога созданные "позднее" имеют бОльшее значение RecId. Если это не так, то нужны дополнительные критерии по которым можно выбрать запись лога, если статус у документа может меняться несколько раз в течении дня.

Да и LEFT особого смысла не имеет. Поскольку он предполагает, что есть документы без статуса. Если такое возможно и их тоже надо отобрать, то, конечно, LEFT нужен. В противном случае, лишние проблемы серверу.
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35981937
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Владимир Максимов: я же уже Вам отвечал, что оба Ваших примера (из Вашей же статьи по ссылке) - не работают на mysql, т.е. завешивают последний.
Моя вина в том что не указал сразу что речь идет о запросе на мускул, просто посчитал что язык SQL для обоих "платформ" одинаков...
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35982162
GoshaS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Такая конструкция на MySQL прокатит?
Код: plaintext
1.
2.
3.
SELECT Docs.DocID, DocsStatesLog.DocStateID, DocsStatesLog.DocStateDate , DocsStates.DocStateName, 
(select top  1  DocTypeName from DocsTypes where DocsTypes.DocTypeID = Docs.DocTypeID order by DocTypeID desc) 
FROM Docs 
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35982325
CTAC-KOпросто посчитал что язык SQL для обоих "платформ" одинаков...И были для этого хоть какие-то основания?
В каждой системе своя реализация SQL. Запомните это как аксиому.
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35982506
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CTAC-KO2 Владимир Максимов: я же уже Вам отвечал, что оба Ваших примера (из Вашей же статьи по ссылке) - не работают на mysql, т.е. завешивают последний.
Моя вина в том что не указал сразу что речь идет о запросе на мускул, просто посчитал что язык SQL для обоих "платформ" одинаков...
Не обязательно "завешивают". Просто подобные запросы не оптимизируются. По крайней мере, в FoxPro. Как следствие, если объем таблиц достаточно большой, то время выполнения может быть катострафически большим. Ведь необходимо "тупо" просканировать ВСЕ записи таблицы логов. А это очень много. Вот и возникает ощущение "завешивания".

Для начала, попробуйте убрать "вспомогательные" таблицы. Оставить в запросе только Docs и DocsStatesLog.

В принципе, есть разные приемы, как ускорить выполнение запроса, но все они сводятся к уменьшению объема выборки путем разных "махинаций", очень существенно зависящих от конкретной постановки задачи. Т.е. что именно происходит с полученной выборкой? Для чего она нужна? Можно ли часть информации выбирать "по требованию"?
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35982943
Tohan_ORA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
CTAC-KO,

Если есть возможность создать функцию на сервере,то можно её использовать в запросе,например для Oracle ,будет так(для MySql -может что либо подобное):

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
CREATE OR REPLACE FUNCTION myfunc(v_docID IN  DocsStatesLog.docID%TYPE) 
RETURN DocsStatesLog.DocStateDate%TYPE
IS
  rs DocsStatesLog.DocStateDate%TYPE;
BEGIN
     SELECT MAX(DocStateDate) INTO rs FROM DocsStatesLog WHERE docID=v_docID;
     RETURN rs;
END;

Код: plaintext
1.
2.
3.
4.
5.
SELECT  d.DocID,a.DocTypeName,b.DocStateID,b.DocStateDate,c.DocStateName;
FROM Docs d;
LEFT JOIN DocsTypes a ON a.DocTypeID = d.DocTypeID ;
LEFT JOIN DocsStatesLog b ON b.DocID = d.DocID;
LEFT JOIN DocsStates c ON c.DocStateID  = b.DocStateID;
where b.DocStateDate = myfunc(d.DocID) or b.DocStateDate is null
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35983984
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Владимир Максимов: дело в том, что я пробовал указать вместо DocID реальное значение одного из документов, у которого в журнале было всего 3 записи по смене состояний (всего в логе 40к записей). один фиг - зависание.
2 Tohan_ORA - да, создать процедуры и функции можно, но мне это будет стоить времени, т.к. я не разбирался еще толком что да как. Возможно попробую когда-то в дальнейшем. Пока же интересен вариант выборки.

Вот piva пишет что это проблема мускула и я думаю что так оно и есть...
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35983988
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GoshaSТакая конструкция на MySQL прокатит?
Код: plaintext
1.
2.
3.
SELECT Docs.DocID, DocsStatesLog.DocStateID, DocsStatesLog.DocStateDate , DocsStates.DocStateName, 
(select top  1  DocTypeName from DocsTypes where DocsTypes.DocTypeID = Docs.DocTypeID order by DocTypeID desc) 
FROM Docs 
нет. он на top 1 указывает как на ошибку и в доке по SELECT syntax я такого тоже не встречал, скорей всего не поддерживается, по крайней мере в той версии что у меня
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35984013
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Владимир Максимов: Ваш пример таки работает, если задать DocID. Это мой, с МАХ() даже с указанным DocID зависал вроде, не помню точно. Просто попробовал еще раз. Значит он работает и в целом, но очень долго если для всей таблицы документов...
...
Рейтинг: 0 / 0
Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
    #35984040
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
индексация по DocID в таблице DocsStatesLog уменьшило время выборки с 764 до 0,6 секунд... Чето я сразу не допер что в этом может быть дело. Интересно что дополнительный индекс там же по дате ничего не дает - видимо потому что на один DocID приходится немного записей
...
Рейтинг: 0 / 0
18 сообщений из 18, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Как сделать выборку c JOIN-ом последних записей из лога по каждому из идентификаторов?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]