Oracle OrderBy匹配互补值

发布于 2025-02-11 07:23:57 字数 846 浏览 2 评论 0原文

我有一张具有以下内容

ID名称的表ID
1包a3
2包B2
3包C1
4包D2
5Package E5

现在我想订购它们,以便两个直接连续的软件包的总和应与值“ 4”。

在上表的情况下,正确的结果可能会如下:

ID名称件包
1a3
2软件包1
3包b2
4包D2
5 25包e5

我的问题是,使用Oracle SQL功能和如果是这样,有人会如何意识到这一点?

I have a table with the following content

IDNAMESIZE
1PACKAGE A3
2PACKAGE B2
3PACKAGE C1
4PACKAGE D2
5PACKAGE E5

Now i would like to order them so that the sum of two directly successive packages shall correspond to the value '4'.

In the case of the table above a right result could look like this:

IDNAMESIZE
1PACKAGE A3
2PACKAGE C1
3PACKAGE B2
4PACKAGE D2
5PACKAGE E5

My question is if this is possible with Oracle SQL functions and if so how someone would realise this ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

耳根太软 2025-02-18 07:23:57

您可以创建管道功能以获取对。

首先创建类型:

CREATE TYPE table_name__obj AS OBJECT(
  id     NUMBER,
  name   VARCHAR2(20),
  "SIZE" NUMBER
);

CREATE TYPE table_name__tbl AS TABLE OF table_name__obj;

然后函数:

CREATE FUNCTION paired_products(
  v_total IN PLS_INTEGER
) RETURN table_name__tbl PIPELINED
IS
  v_tbl table_name__tbl;
  i     PLS_INTEGER;
  i_nxt PLS_INTEGER;
  j     PLS_INTEGER;
BEGIN
  SELECT table_name__obj(id, name, "SIZE")
  BULK COLLECT INTO v_tbl
  FROM   table_name
  ORDER BY "SIZE";
  
  i := v_tbl.FIRST;
  WHILE i IS NOT NULL LOOP
    j := v_tbl.NEXT(i);
    WHILE j IS NOT NULL LOOP
      IF v_tbl(i)."SIZE" + v_tbl(j)."SIZE" = v_total THEN
        EXIT;
      END IF;
      j := v_tbl.NEXT(j);
    END LOOP;

    PIPE ROW(v_tbl(i));
    IF j IS NOT NULL THEN
      PIPE ROW(v_tbl(j));
      v_tbl.DELETE(j);
    END IF;

    i_nxt := v_tbl.NEXT(i);
    v_tbl.DELETE(i);
    i := i_nxt;
  END LOOP;
END;
/

对于示例数据:

CREATE TABLE table_name (ID, NAME, "SIZE") AS
SELECT 1, 'PACKAGE A', 3 FROM DUAL UNION ALL
SELECT 2, 'PACKAGE B', 2 FROM DUAL UNION ALL
SELECT 3, 'PACKAGE C', 1 FROM DUAL UNION ALL
SELECT 4, 'PACKAGE D', 2 FROM DUAL UNION ALL
SELECT 5, 'PACKAGE E', 5 FROM DUAL;

以最小的大小和相应对开始,然后以增加尺寸的对开始,以排序输出行。如果发现没有匹配对的行,则立即输出,发现没有对。

idname大小
3软件包c1
1软件包a3
2软件包b2
4软件包d2
5软件包e5

db< = 74928BF944781459CF1D62E0E0F5AF51“ rel =“ nofollow noreferrer”>此处

You can create a PIPELINED function to get the pairs.

First create the types:

CREATE TYPE table_name__obj AS OBJECT(
  id     NUMBER,
  name   VARCHAR2(20),
  "SIZE" NUMBER
);

CREATE TYPE table_name__tbl AS TABLE OF table_name__obj;

And then the function:

CREATE FUNCTION paired_products(
  v_total IN PLS_INTEGER
) RETURN table_name__tbl PIPELINED
IS
  v_tbl table_name__tbl;
  i     PLS_INTEGER;
  i_nxt PLS_INTEGER;
  j     PLS_INTEGER;
BEGIN
  SELECT table_name__obj(id, name, "SIZE")
  BULK COLLECT INTO v_tbl
  FROM   table_name
  ORDER BY "SIZE";
  
  i := v_tbl.FIRST;
  WHILE i IS NOT NULL LOOP
    j := v_tbl.NEXT(i);
    WHILE j IS NOT NULL LOOP
      IF v_tbl(i)."SIZE" + v_tbl(j)."SIZE" = v_total THEN
        EXIT;
      END IF;
      j := v_tbl.NEXT(j);
    END LOOP;

    PIPE ROW(v_tbl(i));
    IF j IS NOT NULL THEN
      PIPE ROW(v_tbl(j));
      v_tbl.DELETE(j);
    END IF;

    i_nxt := v_tbl.NEXT(i);
    v_tbl.DELETE(i);
    i := i_nxt;
  END LOOP;
END;
/

Which, for the sample data:

CREATE TABLE table_name (ID, NAME, "SIZE") AS
SELECT 1, 'PACKAGE A', 3 FROM DUAL UNION ALL
SELECT 2, 'PACKAGE B', 2 FROM DUAL UNION ALL
SELECT 3, 'PACKAGE C', 1 FROM DUAL UNION ALL
SELECT 4, 'PACKAGE D', 2 FROM DUAL UNION ALL
SELECT 5, 'PACKAGE E', 5 FROM DUAL;

Outputs the rows in the order starting from the smallest size and the corresponding pair and then in increasing sized pairs. If a row is found that does not have a matching pair then it is output immediately it is found not to have a pair.

IDNAMESIZE
3PACKAGE C1
1PACKAGE A3
2PACKAGE B2
4PACKAGE D2
5PACKAGE E5

db<>fiddle here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文