【问题标题】:How can I select a different column from each row?如何从每一行中选择不同的列?
【发布时间】:2019-07-16 00:03:46
【问题描述】:

我有一个包含三列和三条记录的表。如何选择第一列的第一个值,第二列的第二个值,第三列的第三个值?

table
============
test_tab

id1   id2   id2
===   ===   ====
100   400   700
200   500   800
300   600   900

所需的输出,如:

100  500  900

如何使用 Oracle SQL 或 PL/SQL 实现这一目标?

【问题讨论】:

  • 如果 id2 的行数为 4 会是什么输出
  • SQL 表代表 无序 集。表中没有“第一”行。
  • 请先提供有效数据。同一张表中的2列同名无效!

标签: sql oracle plsql


【解决方案1】:

首先,如何确定哪一行是第一行,哪一行是第二行?

Oracle 不保证记录的顺序,必须明确使用order by 子句进行排序,否则,我们可以说随机顺序(默认查询输出)

根据您的测试数据和结果,您可以使用以下查询: 注意:我将第三列视为 ID3 并使用 ID1 对行进行排序

SELECT
    MAX(CASE RN
        WHEN 1   THEN ID1
    END) AS ID1,
    MAX(CASE RN
        WHEN 2   THEN ID2
    END) AS ID2,
    MAX(CASE RN
        WHEN 3   THEN ID3
    END) AS ID3
FROM
    (
        SELECT
            ID1,
            ID2,
            ID3,
            ROW_NUMBER() OVER(
                ORDER BY
                    ID1
            ) RN
        FROM
            TEST_TAB
    );

干杯!!

【讨论】:

    【解决方案2】:

    您将需要一种方法来确定“第一”的含义。 在 Oracle 中,这是解决问题示例的一种方法:

    create table test_tab(
      id1 integer,
      id2 integer,
      id3 integer
    );
    
    insert into test_tab values(100,400,700);
    insert into test_tab values(200,500,800);
    insert into test_tab values(300,600,900);
    
    commit;
    
    select sum(decode(pos, 1, id1, null)) id1,
           sum(decode(pos, 2, id2, null)) id2,
           sum(decode(pos, 3, id3, null)) id3
      from(
        -- this subquery produces a rank column for the whole dataset
        -- with an explicit order
        select id1, id2, id3, rank() over (order by id1, id2, id3) pos from TEST_TAB
      );
    

    在此实现中,子查询用于建立行的排序,基于rank() 函数添加一个新的pos 列。

    sum(decode(pos, 3, id3, null)) 构造是一种 Oracle 习惯用法,用于选择一个特定行(在本例中为第 3 行)而忽略其他行。 基本上,对于您的三行,decode 将导致 NULL 用于除具有指定数字的行之外的任何行,因此 id3 的表达式对于第三行将只有一个非空值,因此该组的总和将等于第 3 行中的 id3

    有很多方法可以做到这一点,这只是一种,您可能需要对此实现进行一些调整,以使其在您的实际代码中正常工作。

    【讨论】:

      猜你喜欢
      • 2012-10-20
      • 1970-01-01
      • 2018-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-06
      • 1970-01-01
      相关资源
      最近更新 更多