Sql “按级别连接”不会随每行字段的更改而调整
让我从设置场景开始提问 我有一个test2表,它只包含两个字段:productid和productlife,我想显式地列出产品的所有年份 比如说, 对于产品A,我想列出 Y15 | Y16 | Y17 | Y18 | Y19,A 对于产品B,使用相同的规则,我应该得到 Y18 | Y19,B 我的sql不会产生我想要的结果:Sql “按级别连接”不会随每行字段的更改而调整,sql,oracle,Sql,Oracle,让我从设置场景开始提问 我有一个test2表,它只包含两个字段:productid和productlife,我想显式地列出产品的所有年份 比如说, 对于产品A,我想列出 Y15 | Y16 | Y17 | Y18 | Y19,A 对于产品B,使用相同的规则,我应该得到 Y18 | Y19,B 我的sql不会产生我想要的结果: SELECT ( SELECT listagg("Year",'|') within GROUP ( ORDER BY "Year") "Prefix" F
SELECT
(
SELECT listagg("Year",'|') within GROUP (
ORDER BY "Year") "Prefix"
FROM
(
SELECT 'Y'
||(TO_CHAR(SYSDATE,'yy')-LEVEL) "Year"
FROM dual
CONNECT BY level<=r.productlife
)
) "Prefix", productid
FROM TEST2 r
谢谢 这个查询就可以了,但我觉得一定有更好的方法: 选择t.productid,s.yr 从Test2T开始 内部连接选择ROWNUM RN,到_CHARSYSDATE,'YY'-ROWNUM+1年 从双d 按标高连接=s.rn 由t.productid,s.yr订购;
这里有一个SQLFIDLE供您使用:如果它不一定要使用connect by,另一种方法可能是将其显式编写为函数:
with
function list_years(n number) return varchar2 as
end_year date := trunc(sysdate,'YYYY');
start_year date := add_months(end_year, (n*-12));
y date;
years_list varchar(200);
begin
for i in reverse 1..n loop
y := add_months(sysdate, -12 * i);
years_list := years_list || to_char(y,'"Y"YY"|"');
end loop;
return rtrim(years_list,'|');
end list_years;
select productid
, productlife
, list_years(productlife) as prefix
from test2
/
你能解释一下为什么5年你想要5年,1年你想要2年吗?@gsalem:我道歉。。打字错误,应该是2年。。让我调整一下,您的查询在编辑后返回正确答案,否?至少我通过你的提问得到了你想要的答案。谢谢@Del。你的解决方案似乎神奇地奏效了。问题:为什么您需要加入t.productlife>=s.rn?我可以详细解释一下吗?我对它背后的机制有点模糊。@user1205746-很抱歉耽搁了。好几天没播了。子查询将创建一个视图,其中包含目录中每年最长产品寿命的行。联接中的>=确保您只获取对当前产品有效的行。因此,如果您的最大产品寿命为5,子查询将有[[1,20][2,19][3,18][4,17][5,16]]。如果当前产品只有两年的使用寿命,它只会占据前两行,因为只有前两行的产品寿命大于或等于rownum。不必使用Connect by,我只是不够聪明,无法使用函数,因为我在Oracle还是新手。你的解决方案很优雅。我感谢你分享你的知识。
with
function list_years(n number) return varchar2 as
end_year date := trunc(sysdate,'YYYY');
start_year date := add_months(end_year, (n*-12));
y date;
years_list varchar(200);
begin
for i in reverse 1..n loop
y := add_months(sysdate, -12 * i);
years_list := years_list || to_char(y,'"Y"YY"|"');
end loop;
return rtrim(years_list,'|');
end list_years;
select productid
, productlife
, list_years(productlife) as prefix
from test2
/