Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Полное внешнее объединение / 21 сообщений из 21, страница 1 из 1
04.09.2003, 13:16
    #32255806
SergeySV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
Я так понимаю что SQL Access не поддерживает полное внешнее объединение, а мне надо объединить две таблицы так, чтобы все записи из обеих таблиц были отобраны(типа LEFT JOIN и RIGHT JOIN одновременно). Подскажите, как грамотнее это сэмулировать??? а то пока мне в голову только всякие доп. запросы лезут в голову, может что поэлегантнее есть (через самообъединение попробовать)?
...
Рейтинг: 0 / 0
04.09.2003, 13:23
    #32255816
zz
zz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
Я делал через третью таблицу. Напр, есть таблица "Номенклатура" с всеми кодами товара, делаешь LEFT JOIN к таблице "Расход" по коду товара и LEFT JOIN к таблице "Приход" тоже по коду товара. Таблицы "Расход" и "Приход" оказываются связанными двухсторонним объединением.
...
Рейтинг: 0 / 0
04.09.2003, 14:59
    #32255940
АлексейК
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
предположу но не ручаюсь ... а проверять не на чем ...

select *
from T1 , T2
where T1.id = T2.id or T1.id is null or T1.id not in (select id from T2) or T2.id is null or T2.id not in (select id from T1)
...
Рейтинг: 0 / 0
04.09.2003, 15:07
    #32255953
SergeySV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
Ок, интересно, ща проверим (до этих "not in (select..." я бы сам наверное не допер) :)
...
Рейтинг: 0 / 0
04.09.2003, 17:13
    #32256227
SergeySV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
2АлексейК: неаа, не подходит такой вариант. Он знаешь че делает: на каждую запись из T1 ставит все записи из T2.
Будем искать дальше... ща попробую переделать твой вариант...
...
Рейтинг: 0 / 0
04.09.2003, 17:48
    #32256268
assa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
1. чтоб работало как предложил <АлексейК> нужно дополнить таблицы (обе) пустой записью (юнионы). Но потом еще и убрать полностью пустую из результирующего набора.

2. Вар-нт zz сводится к пристыковке справа и слева к юниону из ключей (точнее -полей связи) обеих.
...
Рейтинг: 0 / 0
04.09.2003, 17:55
    #32256273
SergeySV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
2assa: Пустую говоришь, ща посмотрим....

на счет варианта zz, тут я неочень допираю пока, union это конечно замечательно, но тогда по его совету, мне сначала надо получить таблицу со всеми уник. Id из T1 и T2, так?
...
Рейтинг: 0 / 0
04.09.2003, 17:57
    #32256277
TRoUbLEs
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
Ну примерно так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT Счет_фактура.Сумма, ТТН_приход.Стоимость
FROM Счет_фактура INNER JOIN ТТН_приход ON Счет_фактура.[Уникальный номер] = ТТН_приход.СчетФактура
union
SELECT Счет_фактура.Сумма, ТТН_приход.Стоимость
FROM Счет_фактура LEFT JOIN ТТН_приход ON Счет_фактура.[Уникальный номер] = ТТН_приход.СчетФактура
WHERE (((ТТН_приход.Стоимость) Is Null))
union
SELECT Счет_фактура.Сумма, ТТН_приход.Стоимость
FROM Счет_фактура RIGHT JOIN ТТН_приход ON Счет_фактура.[Уникальный номер] = ТТН_приход.СчетФактура
WHERE (((Счет_фактура.Сумма) Is Null));
...
Рейтинг: 0 / 0
04.09.2003, 18:05
    #32256290
АлексейК
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
2 TRoUbLEs

забыл я как себя ведет в MDB union и union all ...

с появлением дубликатов проблем не будет?

а имеющиеся дубликаты не удалятся?
...
Рейтинг: 0 / 0
04.09.2003, 18:11
    #32256301
SergeySV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
Да, с union я думаю самый реальный вариант, потому как через WHERE с доп. SELECT(да и без него тоже) получается совершенно не то.
При обработке запросов на объединение где указаны 2 таблицы, я так понимаю Access, делает следующее: он берет первую запись из T1 и начинает пробегать по всем записям из T2 отбирая их по условию в WHERE.
Если мы в WHERE пишем T1.id=T2.id, тогда все OK, отбираются только совпавшие записи и никаких тебе двойников....
А если мы добавляем какие-нибудь другие условия на НЕСОВПАДЕНИЕ типа T1.id<>T2.id или T1.id not in (select id from T2), то оно (как я уже говорил выше) проверяется между записями по принципу 1зап. T1- все зап. T2, 2зап. T1- все зап. T2 и т.д. и естественно несовпадающих дофига и получаем на каждую запись из T1 по куче записей из T2 (которые уже успели совпасть с другими из T1).

Так что думаю одним WHERE, без LEFT JOIN и UNION эту задачу нереально решить, но это только мое мнение, к которому я пришел эспериментируя с этими таблицами...
...
Рейтинг: 0 / 0
04.09.2003, 18:12
    #32256303
TRoUbLEs
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
То АлексейК:
Тот код, который я привел, лично у меня дубликатов вроед как не вернул (может я просмотрел, конечно). Но чтобы стопудово их не было, надо тогда тянуть еще и ключевые поля по ним делать условие.
Для перестраховки, конечно, можно еще написанть (Not In (SELECT.... )), но думаю, что это лишнее, если правильно организована связь по таблицам.
А вот с SELECT ALL как раз и могут быть проблемы ИМХО.
а имеющиеся дубликаты не удалятся?
Что значит "имеющиеся дубликаты"??? Это как такое возможно, если организовать отбор и условие по ключеванному полю??? Что-то я тут не догнал. :(
...
Рейтинг: 0 / 0
04.09.2003, 18:20
    #32256308
SergeySV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
2TRoUbLEs: ситуация такая, что между таблицами нет никакой связи, кроме того что они имеют практически одинаковую структуру. По смысловой нагрузке, эти таблицы являются просто двойниками: они приходят в базу из разных источников и их надо сравнить и показать различия (ну и так еще по мелочи...)
...
Рейтинг: 0 / 0
04.09.2003, 18:23
    #32256311
SergeySV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
по мелочи - это в этих таблицах есть поле сумма и надо показать записи с несовпадающими суммами

Это я думаю к предложенному варианту TRoUbLEs в первый SELECT просто добавить WHERE T1.Summa=T2.Summa
...
Рейтинг: 0 / 0
04.09.2003, 18:24
    #32256315
SergeySV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
Блин, вернее T1.Summa<>T2.Summa
...
Рейтинг: 0 / 0
04.09.2003, 18:47
    #32256339
TRoUbLEs
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
То SergeySV:
Хе. так тогда тебе не WHERE... нужно, а связь попробовать по этим полям сделать. Но хлопотно это. Скорее всего даже не получится, ибо может вылезти огромный гемор.
Если тебе надо сравнения, то я бы сначала стал сравнивать Общую сумму (т.е. просуммировал бы две таблички и посмотрел бы сумму). Если они сходятся, значит все гут, если нет, то ищем ошибку.
Как вариант, можно попробовать отсортировать мой код по сумме и стоимости и где цифирки не бьются искать проблему. Надеюсь идея понятна.
P.S. А вообще, когда стоит задача сравнения данных из несвязанных таблиц, то тут такая морока начинается, если честно. :( Многое, все равно приходится делать ручками. Можно, конечно программно попробовать это сделать (даже небольшой алгоритмик в голове возник), но это такой гемор, что быстрее и качественнее все сделать самому.
...
Рейтинг: 0 / 0
04.09.2003, 18:52
    #32256345
SergeySV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
Спасибо всем за помощь и предложения.

Код предложенный 2TRoUbLEs работает безотказно, двойников нет.
2TRoUbLEs: отдельное спасибо ... :-)

правда моя идея с WHERE не прокатывает, че-то Access плюет на это условие, времени уже нет, завтра буду разбираться дальше, хотя странно, почему это...
...
Рейтинг: 0 / 0
05.09.2003, 10:35
    #32256658
SergeySV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
C утра разобрался с доп. условием, все оказалось несколько сложнее, чем мне думалось вчера.
Мне надо было изменить запрос TRoUbLEs, добавив туда доп. условие: в полях T1.S и T2.S хранится сумма и отобрать надо поля, у которых T1.S<>T2.S.
Я вчера наивно думал, что добавив после ON (T1.Id=T2.Id) еще AND (T1.S<>T2.S), все будет путем, однако эта штука прокатила только для первого запроса из этих union - с INNER JOIN.
А вот для FROM T1 LEFT JOIN T2 ON (T1.id=T2.id) AND (T1.S<>T2.S) - он делает очень интересную вещь:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Изначально в таблицах:
[T1.Id]  [T1.S]  [T2.Id]  [T2.S]
    1           100      (строки сдвинуты на одну для удобст. сравн.)
    2           101         2          1000   
    3           102         3          102 
                          4          103 

После запроса: FROM T1 LEFT JOIN T2 ON (T1.id=T2.id) AND (T1.S<>T2.S) выводит:

[T1.Id]  [T1.S]  [T2.Id]  [T2.S]
    1           100    
    2           101         2          1000   
    3           102         3         ____
                          4          103 

Т.е. мы хотели записи Id=3 выкинуть, потому как они T1.S=T2.S, а он ее показал и в полях с [T2.Id], [T2.S] просто пишет NULL.
Если конечно хорошо подумать, то он в принципе прав. Ведь он сначала отбирает все записи, которые удовлетворяют между собой условиям: (T1.id=T2.id) AND (T1.S<>T2.S), а потом еще те записи слева(из T1), которые не удовлетворяют указанному условию - вот мы и получаем... хе-хе вообщем в конце рабочего дня до того не всегда сразу допрешь...

Чтобы это обойти, я перенес условие (T1.S<>T2.S) в WHERE, добавив туда еще проверку на (T2.S Is Null), весь код:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT  *
FROM T1 INNER JOIN T2 ON (T1.Id=T2.Id) AND (T1.S<>T2.S)
UNION
SELECT *
FROM T1 LEFT JOIN T2 ON T1.id=T2.id
WHERE (T1.S<>T2.S) OR (T2.S Is Null)
UNION 
SELECT *
FROM T1 RIGHT JOIN T2 ON T1.id=T2.id
WHERE (T1.S<>T2.S) OR (T1.S Is Null)
...
Рейтинг: 0 / 0
05.09.2003, 13:28
    #32256951
TRoUbLEs
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
То SergeySV:
Я тебе сразу указал на гемор, который ты получаешь, если у тебя нет никакой связи между таблицами. (см. 18:47) Но как я смотрю дальше, все-таки какая-то связь есть. :)
Я вчера наивно думал, что добавив после ON (T1.Id=T2.Id) еще AND (T1.S<>T2.S)
Какой смыл с этом не подскажешь???? Или ты хочеь, чтобы тебе выводились только те записи, которые не совпадают, а совпадающие опустить??? Тогда согласен.
...
Рейтинг: 0 / 0
05.09.2003, 14:13
    #32257034
SergeySV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
Да, ты правильно понял, по исходной задаче совпадающие записи надо было опустить.
...
Рейтинг: 0 / 0
05.09.2003, 15:18
    #32257162
bazaea
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
Код: plaintext
1.
2.
3.
4.
5.
SELECT *
FROM T1 LEFT JOIN T2 ON T1.id=T2.id
UNION 
SELECT *
FROM T1 RIGHT JOIN T2 ON T1.id=T2.id

этого должно быть вполне достаточно, если в самих Т1 и Т2 не содержатся повторяющиеся записи. Если содержаться, то будут выведен только 1 экземпляр.
UNION - убирает повторяющиеся записи.
В LEFT или RIGHT уже содержится INNER.

Это что касается OUTER, далее

Я вчера наивно думал, что добавив после ON (T1.Id=T2.Id) еще AND (T1.S<>T2.S), все будет путем, однако эта штука прокатила только для первого запроса из этих union - с INNER JOIN.

А как же, в INNER ты отбираешь записи с совпадающими ID и не совпадающими суммами. А в LEFT и RIGHT приведенном TroUbLEs коде сверяешь сумму одной записи с суммой несуществующей записи.
...
Рейтинг: 0 / 0
08.09.2003, 11:07
    #32258120
SergeySV
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Полное внешнее объединение
Признаю себя ослом!!! :-)
да, можно и без INNER (а если и использовать INNER, тогда в LEFT/RIGHT надо добавить условие (T2.S Is Nul)/(T1.S Is Nul), т.е. чтобы добавить только отсут. записи слева и справа)

В итоге:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
SELECT *
FROM T1 LEFT JOIN T2 ON T1.id=T2.id
WHERE (T1.S<>T2.S) OR (T2.S Is Null)
UNION
SELECT *
FROM T1 RIGHT JOIN T2 ON T1.id=T2.id
WHERE (T1.S<>T2.S) OR (T1.S Is Null)
...
Рейтинг: 0 / 0
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Полное внешнее объединение / 21 сообщений из 21, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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