powered by simpleCommunicator - 2.0.38     © 2025 Programmizd 02
Форумы / SQLite [игнор отключен] [закрыт для гостей] / Пересечение таблиц
12 сообщений из 12, страница 1 из 1
Пересечение таблиц
    #38761440
Volume05
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день всем.

Есть три таблицы A, B, и С. Есть связь (допустим 1:1) B.IDa=A.ID и C.IDa=A.ID И ещё связь (один ко многим) C.IDb = B.ID.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
CREATE TABLE A
(ID INTEGER NOT NULL PRIMARY KEY,
 Name CHAR(100));

CREATE TABLE B
(ID INTEGER NOT NULL PRIMARY KEY,
 IDa INTEGER NOT NULL,
 FOREIGN KEY(IDa) REFERENCES A(ID) ON DELETE CASCADE ON UPDATE CASCADE);

CREATE TABLE С
(ID INTEGER NOT NULL PRIMARY KEY,
 IDa INTEGER NOT NULL,
 IDb INTEGER NOT NULL,
 FOREIGN KEY(IDb) REFERENCES B(ID) ON DELETE CASCADE ON UPDATE CASCADE,
 FOREIGN KEY(IDa) REFERENCES A(ID) ON DELETE CASCADE ON UPDATE CASCADE);



Делается выборка (назовем её Т) из таблицы A, следовательно, мне нужно выбрать связанные записи из таблицы B, но B косвенно связана ещё с другими записями из таблицы A т.е.

Код: sql
1.
2.
3.
4.
5.
SELECT ID FROM A WHERE ID IN
(SELECT DISTINCT C.IDa   FROM B 
INNER JOIN C ON C.IDb = B.ID
INNER JOIN T ON B.IDa = T.ID
ORDER BY  C.IDa);


;если честно, не проверял этот запрос

Результат этого запроса, также добавляется в выборку T и получается необходимо проделывать это снова и снова, пока количество добавляемых записей не будет = 0. Вопрос, реально сделать проще? Одним-двумя запросами.
...
Рейтинг: 0 / 0
Пересечение таблиц
    #38762803
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Во первых, у тебя потенциальная проблема в таблице C. Может получиться так, что С->IDa показывает на одну запись в A, а C->IDb->IDa показывает на другую запись в A. Что ты будешь делать в этом случае?

Во вторых, а вопрос то в чем?
...
Рейтинг: 0 / 0
Пересечение таблиц
    #38762813
Volume05
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White OwlВо первых, у тебя потенциальная проблема в таблице C. Может получиться так, что С->IDa показывает на одну запись в A, а C->IDb->IDa показывает на другую запись в A. Что ты будешь делать в этом случае?
Да, такое может быть и правильно. Можно даже сказать в этом и состоит вопрос.

Ситуация следующая, пользователь делает выборку из таблицы А, мне надо программно сделать выборку из таблицы B, по связи B.IDa=>A.ID, здесь проблем нет. Но записи в таблицы B связаны ещё из другими записями из таблицы А (но не напрямую, а через таблицу С). Следовательно, мне надо, добавить в пользовательскую выборку дополнительные записи из таблицы А (C.IDa=>A.ID). (тот запрос из первого сообщения как раз это и делает (просто я UPDATE не стал писать)).

Фишка в том, что после этого у меня получается новая "пользовательская" выборка из таблицы А. Ну как бы надо повторять всё заново, можно сделать это программно, в цикле. Вопрос: Можно ли сделать это с помощью SQL? если можно, то как?
...
Рейтинг: 0 / 0
Пересечение таблиц
    #38762814
Volume05
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В первом сообщении неправильно написал. Связь С.IDa=A.ID один ко многим.
...
Рейтинг: 0 / 0
Пересечение таблиц
    #38763819
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И все-же объясни (чрезвычайно желательно с примерами) что именно ты хочешь выбрать?
Что запрашивает пользователь и что он должен получить? И при чем здесь update?
...
Рейтинг: 0 / 0
Пересечение таблиц
    #38764185
Volume05
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ок. попробую ещё раз. К черту эти ABC...

Программа связана с мат. моделированием. Есть три таблицы. 1)Временные ряды(dtSets) 2)модели(dtModels) они содержат ссылки на временные ряды, как на функцию(IDSet) и как на аргументы (таблица аргументов). 3)ну и соответственно есть таблица аргументов (dtArguments) это либо другие временные ряды, либо тот же самый ряд, к которому принадлежит модель.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
CREATE TABLE dtSets
(ID INTEGER NOT NULL PRIMARY KEY,
 NameSet CHAR(100));

CREATE TABLE dtModels
(ID INTEGER NOT NULL PRIMARY KEY,
 IDset INTEGER NOT NULL,
 Name CHAR(70),
 FOREIGN KEY(IDset) REFERENCES dtSets(ID) ON DELETE CASCADE ON UPDATE CASCADE);

CREATE TABLE dtArguments
(ID INTEGER NOT NULL PRIMARY KEY,
 IDModel INTEGER NOT NULL,
 IDSet INTEGER NOT NULL,
 FOREIGN KEY(IDModel) REFERENCES dtModels(ID) ON DELETE CASCADE ON UPDATE CASCADE,
 FOREIGN KEY(IDSet) REFERENCES dtSets(ID) ON DELETE CASCADE ON UPDATE CASCADE);



Пользователь хочет выбрать несколько рядов и сохранить их в «наш» файловый формат. Это происходит по нескольким запросам, поэтому я создаю временную таблицу (TempSets) идентичную dtSets. Вместе с временными рядами мне надо также сохранить их модели. Выбрать модели по связи dtModels.IDSet=dtSets.ID я могу. Как я говорил, модель может содержать другие ряды (т.е. как аргументы), которые пользователь не выбирал напрямую, но их надо добавить в TempSets:

Код: sql
1.
2.
3.
4.
5.
6.
INSERT INTO TempSets
(ID, NameSet)
SELECT * FROM dtSets WHERE ID IN
(SELECT DISTINCT dtArguments.IDSet   FROM dtModels 
INNER JOIN dtArguments ON dtArguments.IDmodel = dtModels.ID
INNER JOIN TempSets ON dtModels.IDSet = TempSets.ID);



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

Попробую пример показать:

Временные ряды
ID NameSet1A2B3C4D5E6X7Y8Z

Модели
IDIDSetName11ModelA22ModelB33ModelC44ModelD55modelE

Аргументы
IDIDModelIDSet111212324425525631743855

Пользователь выбрал ряды:
TempSets
ID NameSet1A

Значит, мне надо сохранить модель ModelA. Она имеет следующие аргументы:
IDIDModelIDSet111212

Добавляем в пользовательскую выборку недостающие ряды:
TempSets
ID NameSet1A2B

Т.е. надо уже сохранять две модели: ModelA, ModelB. Смотрим их аргументы:
IDIDModelIDSet111212324425525
Таким образом, мне надо ещё добавить временные ряды D и E.
TempSets
ID NameSet1A2B4D5E

Ну и так далее.
Вопрос. Реально обойтись без цикла? И сделать всё в SQL?
...
Рейтинг: 0 / 0
Пересечение таблиц
    #38764215
Volume05
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А вообще ладно, проехали.
...
Рейтинг: 0 / 0
Пересечение таблиц
    #38765277
Фотография VSVLAD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Volume05,

Реально, это рекурсивный запрос должен быть. На SQLite не пробовал такие писать, но если хотите ищите по SQLite CTE
...
Рейтинг: 0 / 0
Пересечение таблиц
    #38765344
Фотография VSVLAD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вроде что-то похожее выдаёт, вообщем надо проверить. Пользовался официальной документацией

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
with recursive
     allSets(ID, NameSet) as (     

        select ID, NameSet
        from dtSets        
        where dtSets.NameSet = 'A'

        union
        
        select dtSetsNew.ID, dtSetsNew.NameSet
        from allSets        
        inner join dtModels on allSets.ID = dtModels.IDSet
        inner join dtArguments on dtArguments.IDModel = dtModels.ID        
        inner join dtSets as dtSetsNew on dtArguments.IDSet = dtSetsNew.ID

  )
select * from allSets


Результат выборки

IDNameSet1A2B4D5E3C
Для проверки можно воспользоваться вот такой "лесенкой"
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
-- Уровень 3
select distinct dtSetsNew.ID, dtSetsNew.NameSet
from (        
        -- Уровень 2
        select distinct dtSetsNew.ID, dtSetsNew.NameSet
        from (  -- Уровень 1
                select dtSetsNew.ID, dtSetsNew.NameSet
                from (  -- Уровень 0
                        select distinct ID, NameSet
                        from dtSets        
                        where dtSets.NameSet = 'A'    ) allSets        
                inner join dtModels on allSets.ID = dtModels.IDSet
                inner join dtArguments on dtArguments.IDModel = dtModels.ID        
                inner join dtSets as dtSetsNew on dtArguments.IDSet = dtSetsNew.ID
        ) allSets        
        inner join dtModels on allSets.ID = dtModels.IDSet
        inner join dtArguments on dtArguments.IDModel = dtModels.ID        
        inner join dtSets as dtSetsNew on dtArguments.IDSet = dtSetsNew.ID
) allSets        
inner join dtModels on allSets.ID = dtModels.IDSet
inner join dtArguments on dtArguments.IDModel = dtModels.ID        
inner join dtSets as dtSetsNew on dtArguments.IDSet = dtSetsNew.ID
...
Рейтинг: 0 / 0
Пересечение таблиц
    #38765585
Volume05
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
VSVLAD,

Ухты. не ожидал такого подробного ответа. Спасибо.

Реальные таблицы у меня, чуть сложнее, да и ещё не разобрался с этими запросами, но думаю должно сработать. По крайней мере, для описанного примера, твой запрос работает и на моих таблицах.
...
Рейтинг: 0 / 0
Пересечение таблиц
    #38766560
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Volume05Ну и так далее.
Вопрос. Реально обойтись без цикла? И сделать всё в SQL?Не вижу смысла делать это в SQL.
При такой организации данных у тебя может быть гигантский результат, вплоть до полного дампа всех трех таблиц.

Лучше делать это все с клиента по частям, по отдельным запросам. Пользователь запросил SetA? Нарисуй ему этот сэт и рядышком кнопочку: "Показать модели в которых этот сэт используется". По ее нажатию показать список моделей, и к нему кнопочку "показать сэты используемые в отмеченных моделях". Ну и тд...
Либо в каком-либо другом виде, типа zoom in/out. Или что там более подходит по предметной области?

Если на запрос одного конкретного сэта у тебя будет всегда выдаваться еще и все связанные с ним - то пользователь потонет в данных.

Ну а если уж действительно настолько сильно нужно вытащить все разом, то проще циклом с клиента.
...
Рейтинг: 0 / 0
Пересечение таблиц
    #38766611
Volume05
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl,

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

White OwlПри такой организации данных у тебя может быть гигантский результат, вплоть до полного дампа всех трех таблиц.

По идеи не должно быть так. Грубо говоря, сэты в одном регионе замыкаются на глобальные характеристики у которых либо авторегрессионные, либо трендовые модели.

White Owl
Лучше делать это все с клиента по частям, по отдельным запросам. Пользователь запросил SetA? Нарисуй ему этот сэт и рядышком кнопочку: "Показать модели в которых этот сэт используется". По ее нажатию показать список моделей, и к нему кнопочку "показать сэты используемые в отмеченных моделях". Ну и тд...
Либо в каком-либо другом виде, типа zoom in/out. Или что там более подходит по предметной области?

Что-то подобное есть, но тут именно нужно сохранить "полные" данные.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / SQLite [игнор отключен] [закрыт для гостей] / Пересечение таблиц
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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