Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
Всем доброе время суток! Мне очень нужно составить запрос, суть которого я попытаюсь изложить на примере. Есть 3 таблицы (это только пример - в реальности в каждой таблице хранятся сотни тысяч записей): "Main" ---------------- NSER [PK]| FK ---------------- 1 | 1 2 | NULL 3 | 2 4 | NULL 5 | 3 "Otz" ----------- ID [PK]| FK ----------- 1 | 1 2 | 1 3 | 2 4 | 3 5 | 3 6 | 3 "Ik" ----------- ID [PK]| Data ----------- 1 | "111" 2 | "222" 3 | "333" 4 | "444" 5 | "555" Так вот, необходимо составить запрос, который возвращал бы результат джоина этих трех таблиц таким образом: "Result" ---------------- NSER | FK ---------------- 1 | "222" 2 | NULL 3 | "333" 4 | NULL 5 | "555" Поясню: 1. джоин надо делать таким образом: Main <-(FK)-> Otz <-(ID)-> Ik 2. из таблицы Otz надо брать соответствие с максимальным ID, для которого есть инфа в Ik. 3. запрос будет выполняться через VFPOLEDB 7.0 4. Объем данных колоссальный, так что по возможности лучше избежать сложных вложенных запросов Спасибо всем дочитавшим до этого места за терпение!-) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.04.2004, 20:16 |
|
||
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
Объясните мне, по крайней мере, почему для приведенного мной примера по-разному работают следующие два запроса: 1. Код: plaintext 1. 2. 3. 2. Код: plaintext 1. 2. 3. ??? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.04.2004, 21:24 |
|
||
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
Следующий запрос выдает искомый рекордсет: Код: plaintext 1. 2. 3. 4. Однако, данный запрос использует отклонение от стандартного синтаксиса GROUP BY (поле k.data отсутствует в списке группировки). Внимание, вопрос: при каких обстоятельствах будет отрабатывать этот запрос, а также чем чревато использование такого отклонения от синтаксиса? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.04.2004, 21:36 |
|
||
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
А вот с этим кодом можно попасть на неприятности, поскольку его результат зависит от расположения данных. (Это зависит не от наличия или отсутствия агрегирующей функции, а от наличия полей, не участвующих в group by или агрег-й ф-ии.) Попробуй-ка вот с такими данными: Код: plaintext 1. 2. 3. 4. 5. 6. 7. не зависит от расположения данных: Код: plaintext 1. 2. 3. 4. Однако я бы использовал навигационный подход, скорее всего, тут он будет работать быстрее (если делать правильно). PS. А про существование антидемидовича знаешь? :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.04.2004, 09:07 |
|
||
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
2 Sjfx: 1) Да, с такими "необычными" данными запрос не будет работать (хотя в реальной таблице все сортировано по id :). 2) Курсор - это круто. А Фокс не потянет подзапроса? Очень уж хочется сделать ОДИН запрос по типу: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 3) А что такое "навигационный" метод? Это значит, что надо "подтягивать" данные из ik для каждого отдельновзятого nser из Main? Т.е. для каждого nser выполнять свой запрос для получения data, так? 4) про антидемидовича не знаю :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.04.2004, 09:49 |
|
||
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
У тебя неправильное понимание того, как работает объединение JOIN Вне завивимости от использования опций LEFT, RIGHT, FULL, INNER в той части данных, где ЕСТЬ данные в обеих связываемых таблицах все они работаею абсолютно одинаково! И работают аналогично объединению по той же связи в условии WHERE. Отличия заключаются в способе обработке записей одной таблицы для которых нет соответствующих записей в другой таблице. Смотрим твой пример: Код: plaintext 1. 2. 3. ik INNER JOIN otz - отбросит все записи из таблицы otz для которых нет записей в таблице ik RIGHT JOIN main - результат предыдущего объединения будет присоединен к данным таблицы main причем в результирующую выборку попадут записи из предыдущего объединения для которых нет соответсвующих записей в таблице main Код: plaintext 1. 2. 3. main LEFT JOIN otz - объединит записи из таблиц main и otz причем будут добавлены записи из таблицы otz для которых нет соответсвующих записей в таблице main INNER JOIN ik - результат предыдущего объединения будет присоединен к данным таблицы ik. Т.е. если в результате предыдущего объединения есть записи, которые не удовлетворяют условию связи с таблицей ik, то они будут отброшены. Если этого надо избежать, то вместо INNER надо использовать повторный LEFT JOIN Итого, в первом запросе у тебя остануться записи из таблицы main с кодами 4,5, а во втором случае они будут отброшены. При использовании группировок не по всем полям команды SELECT FoxPro выбирает (если не ошибаюсь) последние записи (в порядке их физического следования). Поэтому, если в пределах одной группы могут встречаться разные значения, то результат такого запроса - непредсказуемый. У тебя единственный выход (если нужны именно запросы) - делать 2 последовательных запроса: -) Сначала найти максимальные значения ID в таблице Otz (с группировкой по FK) -) Сделать объединение с этой временной таблицей Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Заметь, во втором запросе 2 LEFT JOIN, поскольку INNER JOIN между ik и tmpOtz в таком синтаксисе приведет к потере записей из main для которых нет fk в таблице tmpOtz PS: FoxPro может использовать подзапросы только в директиве WHERE, поэтому в данной задаче неприменим ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.04.2004, 10:04 |
|
||
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
2 Sjfx: Да, вопрос в догонку: как после манипуляций с курсором закрыть только его (в хэлпе я нашел только close all)? Меня, конечно, интересует метод, который бы работал в VFPOLEDB. Сенкс. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.04.2004, 10:13 |
|
||
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
Курсор - это временная таблица, которая автоматически будет закрыта по окончании сеанса работы FoxPro. Если же его надо закрыть принудительно, то для этого используют команду USE USE IN tmpOtz Если не указано имя файла DBF, то команда USE закроет открытую таблицу в текущей или в указанной (опция IN) рабочей области. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.04.2004, 10:25 |
|
||
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
1. Если стопроцентно уверен в отсортированности данных - используй свой запрос и не парься. 2. Можно одним "правильным" запросом, но он намного медленнее... 3. Навигационный метод - обработка данных, использующая следование записей в определённом порядке. Используются команды типа INDEX, set relation, ... Если не знаком - то для срочной задачи не стоит и лезть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.04.2004, 10:52 |
|
||
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
2 ВладимирМ: Спасибо за столь подробный ответ! ВладимирМИтого, в первом запросе у тебя остануться записи из таблицы main с кодами 4,5, а во втором случае они будут отброшены. Осмелюсь возразить: у меня во втором запросе "убиваются" записи с nser=2 и 4. Однако, я разобрался. Действительно, эти джоины должны работать по-разному. 2 Sjfx: Идея c корявым GROUP BY точно будет работать, если id в Otz будет отсортирован (т.е. при выборе select * from otz записи будут возвращать id в порядке возрастания)? 2 All: В итоге идея с курсором переросла в такое решение: Код: plaintext 1. 2. 3. 4. 5. Как считаете, насколько оно грамотное? Всем откликнувшимся спасибо! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.04.2004, 11:13 |
|
||
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
Чем в моем курсорном решении поможет NOFILTER? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.04.2004, 11:23 |
|
||
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
В FoxPro при определенных ситуациях команда Select ... INTO CURSOR создает не временную таблицу, а просто накладывает фильтр на таблицу-источник. Соответсвенно, использование такой таблицы в последующем запросе становится невозможным (будет сообщение об ошибке). Чтобы быть уверенным, что будет создана именно временная таблица, а не наложен фильтр и используют опцию NOFILTER. Однако в твоем случае нет условий для наложения фильтра. Всегда будет создана именно временная таблица. Так что можешь и не использовать NOFILTER. Это просто перестраховка. В твоем последнем варианте это конечно будет работать, но ты делаешь лишний шаг - дважды сканируешь таблицу ik - сначала для формирования курсора, а потом для формирования итоговой выборки. Лучше делать так: 1) -) Для определения MAX() объединить main LEFT JOIN otz -) Результат объединить по LEFT ( RIGHT) с ik 2) -) Для определения MAX() объединить ik INNER JOIN otz -) Результат объединить по LEFT ( RIGHT) с main 3) Ранее описанный способ определения MAX() только по таблице otz Посмотри, какой способ будет наиболее быстрым ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.04.2004, 11:54 |
|
||
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
1. Такие фишки на предварительно отсортированных выборках у меня ПОКА ни разу не отказывали (но всё-равно неуютно при каждом переходе на новую версию фокса). 2. Никогда не сокращай алиас до одной буквы "m", чтобы не было недоразумений и путаницы с переменными памяти, они и уточняются префиксом "m". Я дык вообще менее чем 2-х буквенными алиасами на фоксе не пользуюсь, поскольку уже могут существовать уже открытые алиасы с теми же однобуквенными префиксами. Во избежание, так сказать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.04.2004, 15:24 |
|
||
|
Помогите составить запрос - очень нужно!
|
|||
|---|---|---|---|
|
#18+
2 Sjfx: 1. Ну и круто!-) А то что-то мне неохота париться с курсорами - это потребует работы с батчами, которые возвращают два рекордсета :( 2. Не хочу код шибко менять, тем более, что ничего кроме банальных селектов я с фоксой не далаю (а если и делаю, то через другое соединение). Но на будущее обязательно учту! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.04.2004, 17:26 |
|
||
|
|

start [/forum/topic.php?fid=41&fpage=383&tid=1596684]: |
0ms |
get settings: |
9ms |
get forum list: |
14ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
33ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
36ms |
get tp. blocked users: |
1ms |
| others: | 227ms |
| total: | 337ms |

| 0 / 0 |
