2

这是我的情况:

表一包含一组使用 id 作为唯一标识符的数据。该表与大约 6 个其他表具有一对多关系。

给定 Id 为 001 的表 1:表 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 有点弱,我可以使用一些帮助。

4

8 回答 8

3

Table1 上的 LEFT OUTER JOIN Tables2-N

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)
于 2008-09-19T15:42:23.450 回答
2

加入不适合我。我讨厌不得不在客户端解开数据。所有来自左连接的空值。

这是一个不使用联接的基于集合的解决方案。

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)
于 2008-09-19T15:50:41.293 回答
1
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

这实际上取决于您需要将数据输出到报告的格式。

如果您可以提供您希望输出的示例,我可能会提供更多帮助。

于 2008-09-19T15:47:44.437 回答
1

啊! 程序!如果您需要在第一个表的结果之后对其他表的结果进行排序,我的 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

如果您想按初始 ID 对结果进行分组,请使用左外连接,如前所述。

于 2008-09-19T15:42:50.283 回答
1

如果您觉得大胆,最好使用 Crystal 或 Jasper 之类的报告工具,甚至是 XSL-FO。他们有内置的东西来专门处理这个问题。这不是在原始 SQL 中运行良好的东西。

如果所有行(标题以及所有细节)的格式都相同,那么将其作为存储过程也很容易。

我会做什么:将它作为一个连接来做,这样你就会在每一行上都有标题数据,然后使用报告工具进行分组。

于 2008-09-19T15:43:29.423 回答
0

我要做的是在以下查询上打开游标:

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 可能命名为 id,但在其他表中不会有该名称。)

于 2008-09-19T15:51:45.317 回答
0

所有表格的格式都一样吗?如果没有,那么如果您必须有一个可以显示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为 aninsert into并在最后获得一个结果集...

于 2008-09-19T15:56:43.837 回答
0

将所有表连接在一起。

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

然后,您需要汇总代码中的列,以按照您认为合适的方式格式化您的报告。

于 2008-09-19T15:44:10.030 回答