使用 Oracle 中的函数与 3 个相关表将多行连接到一列中
我知道关于同一问题有多个问题,但我找不到可以解决我的问题的问题。我也知道这篇文章,这正是我用于代码的内容以下。我只是遇到了一个小问题...
table_a:
a_id a_name
1 aaa
2 bbb
3 ccc
table_b:
b_id b_name
1 ddd
2 eee
3 fff
table_c
a_id b_id
1 2
1 3
2 1
3 1
3 2
3 3
我有上面的表格,我需要一个 SELECT 语句来完成这个:
a_name list_of_b_name
aaa eee,fff
bbb ddd
ccc ddd,eee,fff
也许我可以使用一些Oracle函数来简化过程,比如WM_CONCAT(还没有尝试过),但我需要使用一个FUNCTION,这是我在查看上面链接的文章后的尝试:
CREATE OR REPLACE
FUNCTION f_test(id IN table_c.a_id % TYPE) RETURN VARCHAR2 IS
l_text VARCHAR2(32767) := NULL;
BEGIN
FOR cur_rec IN (SELECT b_id FROM table_c WHERE a_id = id) LOOP
l_text := l_text || ',' || cur_rec.b_id;
END LOOP;
RETURN LTRIM(l_text, ',');
END;
然后选择像这样:
SELECT a_id, f_test(a_id)
FROM table_c
GROUP BY a_id;
正如上面的代码所期望的(不是我想要的,这就是我得到的):
a_id list_of_b_id
1 2,3
2 1
3 1,2,3
我已经用 SELECT 和 FUNCTION 代码尝试了很多东西,但我似乎无法做我需要的事情......
I know there are multiple questions about this same question but I couldn't find one that would fix my problem. I also know about this article and that's exactly what I used for the code below. I'm just having a little problem...
table_a:
a_id a_name
1 aaa
2 bbb
3 ccc
table_b:
b_id b_name
1 ddd
2 eee
3 fff
table_c
a_id b_id
1 2
1 3
2 1
3 1
3 2
3 3
I have the tables above and I need a SELECT statement that accomplishes this:
a_name list_of_b_name
aaa eee,fff
bbb ddd
ccc ddd,eee,fff
Maybe there are some Oracle functions I can use to simplify the process, like WM_CONCAT (haven't tried), but I need to use a FUNCTION and this is my attempt after looking at the article linked above:
CREATE OR REPLACE
FUNCTION f_test(id IN table_c.a_id % TYPE) RETURN VARCHAR2 IS
l_text VARCHAR2(32767) := NULL;
BEGIN
FOR cur_rec IN (SELECT b_id FROM table_c WHERE a_id = id) LOOP
l_text := l_text || ',' || cur_rec.b_id;
END LOOP;
RETURN LTRIM(l_text, ',');
END;
And then the SELECT goes like this:
SELECT a_id, f_test(a_id)
FROM table_c
GROUP BY a_id;
As expected by the code above (not not what I want, this is what I get):
a_id list_of_b_id
1 2,3
2 1
3 1,2,3
I've tried many things with both the SELECT and FUNCTION code but I can't seem to do what I need...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您需要将您的函数更改为类似于:
然后,您可以使用:
You need to change your function to resemble:
Then, you can use:
更改 SQL 查询以获取 bname 列表而不是 b_ids
从
到
您不应该从表 b 获取 ID,而应该获取名称。
change the SQL Query to get the list of bnames instead of b_ids
from
to
Instead of getting the IDs from table b, you should instead be getting the names.
首先,正如 @OMGPonies 指出的,您需要重写该函数,以便它从 TABLE_B 检索所需的数据。
同样,您需要在查询中加入 TABLE_A:
哦,这真是一个惊喜。关键是,F_TEST 不是聚合函数,因此除非我们也包含该函数,否则 GROUP BY 在这里不起作用:
顺便说一句,如果没有 GROUP BY 子句,我们将得到六行(TABLE_C 中的每一行各一行)。这是我们不想要的。
该解决方案的问题在于性能:该函数针对 TABLE_C 中的每一行执行一次。如果任一表很大,TABLE_B 上的循环会变得有点昂贵。聚合解决方案更有效:
Firstly, as @OMGPonies points out, you need to rewrite the function so it retrieves the required data from TABLE_B.
Likewise you need to join to TABLE_A in the query:
Oh, that was a surprise. The point is, F_TEST is not a aggregating function, so GROUP BY doesn't work here unless we include the function as well:
Incidentally, without the GROUP BY clause we would get six rows (one for each row in TABLE_C). Which we don't want.
The problem with the solution is one of performance: the function is executed once for each row in TABLE_C. That loop on TABLE_B would get a bit expensive if either table were large. The aggregating solution is more efficient: