2008-09-19 19 views
2

这是我的情况:可能与光标/加入有关的问题

表1包含一组使用唯一标识符的数据。这张表与其他大约6张表有着一对多的关系。

给出的表1与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有点弱,我可以使用一些帮助。

+0

什么数据库,你运行这个吗? – chrisb 2008-09-19 15:43:54

+0

是那个伪代码?如果不是,那是哪种语言?它看起来不像transact-SQL。如果我知道答案的格式,我会提出一些建议... – 2008-09-19 15:44:14

回答

3

LEFT OUTER JOIN Tables2-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) 
+0

他只想打印表1中的数据一次。这对你的策略是可行的,但需要更多的逻辑。还要注意,除非你有完全正确的索引集合,否则这种连接类型的查询计划往往非常糟糕。 – user11318 2008-09-19 15:48:55

+0

您从数据库中拉出的内容不一定是您打印的内容。此查询是正确的 - 客户端逻辑应该只在显示Table1数据时才会更改。任何类型的报告创建软件都能为您做到这一点。 – 2008-09-19 16:17:15

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想组的结果,使用左外连接,如前面提到的。

1

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

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

我会做什么:将它作为连接,因此您将在每一行都有标题数据,然后使用报告工具进行分组。

0

将所有表格连接在一起。

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

然后,您将需要汇总代码中的列以根据需要设置报告的格式。

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 

这实际上取决于您需要输入到报表中的数据的格式。

如果你可以给出一个你想如何输出的例子,我可能会帮助更多。

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) 
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,但不会在在其他表中具有该名称。)

0

是否所有的表都具有相同的格式?如果不是,那么如果你必须有一个能够显示不同类型的行的报告。如果你只对同一列感兴趣,那么它更容易。

大多数数据库都有某种形式的动态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,并得到一个结果集结尾......