枚举内部连接中的行
Posted
技术标签:
【中文标题】枚举内部连接中的行【英文标题】:Enumerating rows in a inner join 【发布时间】:2017-01-10 08:27:56 【问题描述】:我的桌子
id name num
1 a 3
2 b 4
我需要返回每一行 num 次。我是这样做的。
select DB.BAN_KEY as BAN_KEY, DB.CUST_FULLNAME as CUST_FULLNAME
from TST_DIM_BAN_SELECTED DB
inner join (select rownum rn from dual connect by level < 10) a
on a.rn <= DB.N
生成的表格如下所示。
id name
1 a
1 a
1 a
2 b
2 b
2 b
2 b
但我还需要将组中的每一行都像这样编号。
id name row_num
1 a 1
1 a 2
1 a 3
2 b 1
2 b 2
2 b 3
2 b 4
我该怎么做?
【问题讨论】:
【参考方案1】:您不需要对虚拟表进行内部连接或分析函数来生成行号;您可以在表本身上使用 connect by(及其相应的级别函数),如下所示:
WITH tst_dim_ban_selected AS (SELECT 1 ban_key, 'a' cust_fullname, 3 n FROM dual UNION ALL
SELECT 2 ban_key, 'b' cust_fullname, 4 n FROM dual)
-- end of mimicking your table with data in it. See SQL below
SELECT db.ban_key,
db.cust_fullname,
LEVEL row_num
FROM tst_dim_ban_selected db
CONNECT BY LEVEL <= db.n
AND PRIOR db.ban_key = db.ban_key -- assuming this is the primary key
AND PRIOR sys_guid() IS NOT NULL;
BAN_KEY CUST_FULLNAME ROW_NUM
---------- ------------- ----------
1 a 1
1 a 2
1 a 3
2 b 1
2 b 2
2 b 3
2 b 4
如果表的主键中有除ban_key 之外的其他列,则需要确保它们包含在connect by 子句的prior <column> = <column>
s 列表中。这样 connect by 就可以唯一地识别每一行,这意味着它只在该行上循环,而没有其他行。需要PRIOR sys_guid() IS NOT NULL
以防止发生循环连接。
【讨论】:
【参考方案2】:您可以为此使用解析函数:
Select id, name,
row_number() over (partition by id, name order by id, name)
From(/* your query */) t;
这可以在没有子查询的情况下完成:
Select id, name,
row_number() over (partition by id, name order by id, name)
From /* joins */
【讨论】:
【参考方案3】:你可以用这个:
SELECT db.ban_key AS ban_key, db.cust_fullname AS cust_fullname,
ROW_NUMBER() OVER (PARTITION BY db.n ORDER BY db.ban_key) AS row_num
FROM tst_dim_ban_selected db
INNER JOIN (SELECT rownum rn FROM dual CONNECT BY level < 10) a
ON a.rn <= db.n;
【讨论】:
【参考方案4】:使用递归子查询分解子句:
WITH split ( id, name, rn, n ) AS (
SELECT BAN_KEY, CUST_FULLNAME, 1, N
FROM TST_DIM_BAN_SELECTED
UNION ALL
SELECT id, name, rn + 1, n
FROM split
WHERE rn < n
)
SELECT id, name, rn
FROM split;
【讨论】:
以上是关于枚举内部连接中的行的主要内容,如果未能解决你的问题,请参考以下文章