Возможно, проблема связана с курсором / присоединением - PullRequest
2 голосов
/ 19 сентября 2008

Вот моя ситуация:

Таблица 1 содержит набор данных, которые используют идентификатор для уникального идентификатора. Эта таблица имеет отношение один ко многим примерно с 6 другими таблицами, так что

С учетом Таблицы 1 с Id 001: Таблица 2 может иметь 3 строки с внешним ключом: 001 Таблица 3 может иметь 12 строк с внешним ключом: 001 Таблица 4 может содержать 0 строк с внешним ключом: 001 Таблица 5 может иметь 28 строк с внешним ключом: 001

Мне нужно написать отчет, в котором перечислены все строки таблицы 1 за указанный период времени, за которыми следуют все данные, содержащиеся в нескольких таблицах, которые на него ссылаются.

Мой текущий подход в псевдокоде будет выглядеть так:

select * from table 1
foreach(result) {
  print result;
  select * from table 2 where id = result.id;
  foreach(result2) {
    print result2;
  }
  select * from table 3 where id = result.id
  foreach(result3) {
    print result3;
  }
  //continued for each table
}

Это означает, что один отчет может выполняться в соседнем блоке из 1000 запросов. Я знаю, что это чрезмерно, однако мой sql-fu немного слаб, и я мог бы использовать некоторую помощь.

Ответы [ 8 ]

3 голосов
/ 19 сентября 2008

ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ Таблицы2-N на Таблице1

SELECT Table1.*, Table2.*, Table3.*, Table4.*, Table5.*
FROM Table1
LEFT OUTER JOIN Table2 ON Table1.ID = Table2.ID
LEFT OUTER JOIN Table3 ON Table1.ID = Table3.ID
LEFT OUTER JOIN Table4 ON Table1.ID = Table4.ID
LEFT OUTER JOIN Table5 ON Table1.ID = Table5.ID
WHERE (CRITERIA)
2 голосов
/ 19 сентября 2008

Регистрация не делает это для меня. Я ненавижу распутывать данные на стороне клиента. Все эти нули от присоединения слева.

Вот решение на основе множеств, в котором не используются соединения.

INSERT INTO @LocalCollection (theKey)
SELECT id
FROM Table1
WHERE ...


SELECT * FROM Table1 WHERE id in (SELECT theKey FROM @LocalCollection)

SELECT * FROM Table2 WHERE id in (SELECT theKey FROM @LocalCollection)

SELECT * FROM Table3 WHERE id in (SELECT theKey FROM @LocalCollection)

SELECT * FROM Table4 WHERE id in (SELECT theKey FROM @LocalCollection)

SELECT * FROM Table5 WHERE id in (SELECT theKey FROM @LocalCollection)
1 голос
/ 19 сентября 2008
SELECT * FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.resultid -- this could be a left join if the table is not guaranteed to have entries for t1.id
INNER JOIN table2 t3 ON t1.id = t3.resultid -- etc

ИЛИ, если все данные имеют тот же формат, что и вы.

SELECT cola,colb FROM table1 WHERE id = @id
UNION ALL
SELECT cola,colb FROM table2 WHERE resultid = @id
UNION ALL
SELECT cola,colb FROM table3 WHERE resultid = @id

Это действительно зависит от формата, в котором вам требуются данные для вывода в отчет.

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

1 голос
/ 19 сентября 2008

Возможно, вам лучше использовать такой инструмент отчетности, как Crystal, Jasper или даже XSL-FO, если вы чувствуете смелость. У них есть вещи, встроенные, чтобы справиться именно с этим. Это не то, что хорошо работает в сыром SQL.

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

Что бы я сделал: сделайте это как объединение, чтобы у вас были данные заголовка в каждой строке, а затем используйте инструмент отчетности для группировки.

1 голос
/ 19 сентября 2008

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

Insert Into #rows Select id from Table1 where date between '12/30' and '12/31'
Select * from Table1 t join #rows r on t.id = r.id
Select * from Table2 t join #rows r on t.id = r.id
--etc

Если вы хотите сгруппировать результаты по начальному идентификатору, используйте левое внешнее соединение, как упоминалось ранее.

0 голосов
/ 19 сентября 2008

Все ли таблицы имеют одинаковый формат? Если нет, то если у вас есть отчет, который может отображать n различных типов строк. Если вас интересуют только те же столбцы, тогда это проще.

Большинство баз данных имеют некоторую форму динамического SQL. В этом случае вы можете сделать следующее:

create temporary table from
select * from table1 where rows within time frame

x integer
sql varchar(something)
x = 1
while x <= numresults {
 sql = 'SELECT * from table' + CAST(X as varchar) +  ' where id in (select id from temporary table'
 execute sql
 x = x + 1
}

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

Если для отчета требуются одинаковые 2 или 3 столбца для каждой таблицы, вы можете изменить select * from tablex на insert into и получить один набор результатов в конце ...

0 голосов
/ 19 сентября 2008

Я бы открыл курсоры по следующим запросам:

SELECT * from table1 order by id
SELECT * from table1 r, table2 t where t.table1_id = r.id order by r.id
SELECT * from table1 r, table3 t where t.table1_id = r.id order by r.id

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

0 голосов
/ 19 сентября 2008

Соедините все столы вместе.

select * from table_1 left join table_2 using(id) left join table_3 using(id);

Затем вам нужно будет свернуть столбцы в коде, чтобы отформатировать отчет по своему усмотрению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...