Sql 可能与游标/联接有关的问题

Sql 可能与游标/联接有关的问题,sql,optimization,join,database-cursor,Sql,Optimization,Join,Database Cursor,以下是我的情况: 表1包含一组使用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; se

以下是我的情况:

表1包含一组使用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有点弱,我需要一些帮助

表1上的左外联接表2-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)

啊!!程序!如果需要在第一个表的结果之后对其他表的结果进行排序,我的SQL将如下所示


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

您最好使用诸如Crystal或Jasper之类的报告工具,如果您觉得大胆,甚至可以使用XSL-FO。他们有专门处理这件事的东西。这不是在原始SQL中可以很好地工作的东西

如果所有行(标题和所有细节)的格式都相同,那么作为存储过程也很容易做到


我要做的是:将其作为一个联接,这样您将在每一行上都有标题数据,然后使用报告工具进行分组。

将所有表联接在一起

select * from table_1 left join table_2 using(id) left join table_3 using(id);
然后,您需要在代码中汇总这些列,以便按照您认为合适的格式设置报表

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
这实际上取决于输出到报表所需的数据格式


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

Join不适合我。我讨厌在客户端处理数据。所有从左到右的零

这里有一个基于集合的解决方案,它不使用连接

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)

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

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

然后我会平行移动这些光标,打印结果。您可以执行此操作,因为所有项都以相同的顺序显示。(请注意,我建议表1的主ID可以命名为ID,但它在其他表中不会有该名称。)

所有表的格式都相同吗?如果没有,那么如果您必须有一个可以显示
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
}
从创建临时表
从表1中选择*在时间范围内
x整数
sqlvarchar(某物)
x=1

你在哪个数据库上运行这个?是伪代码吗?如果不是,是哪种语言?在我看来,它不像transact-SQL。如果我知道答案的格式,我会提出一些建议……他只想打印表1中的数据一次。这在你的策略中是可行的,但需要更多的逻辑。还要注意的是,这种类型的连接的查询计划往往非常糟糕,除非您拥有完全正确的索引集。您从数据库中提取的内容不一定是您打印的内容。这个查询是正确的-当Table1数据发生变化时,客户端逻辑应该只显示它。任何类型的报表创建软件都可以很好地为您实现这一点。除了外键之外,表是完全不同的。游标要慢得多。除非我们知道需要游标的额外功能和灵活性,否则最好避免使用它们。当然要慢一点。但我不同意多少。此外,在大多数外部过程语言中,您可以说“atatementhandle”而不是“cursor”,并得到相同的结果。许多数据库中的cursor速度要慢得多。数据库针对集合函数而不是逐行进行优化。我通过更换游标,缩短了一个进程24小时以上。游标通常应该是数据库中的最后手段(我知道ORacle不是这样)。
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
}