Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql “按级别连接”不会随每行字段的更改而调整_Sql_Oracle - Fatal编程技术网

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

让我从设置场景开始提问

我有一个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"
  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
/