【问题标题】:Select distinct values in each 150 columns of a table在表的每 150 列中选择不同的值
【发布时间】:2021-08-16 22:14:56
【问题描述】:

需要建立一个查询,我有一个有 20 亿行和 150 列的表。

需要找出 150 个不同列中的每一个中的不同值并将其存储在一个表中?

【问题讨论】:

  • 假设一个表有 2 列和以下数据,预期的结果是什么? (1,1),(1,2),(2,3)
  • 在第 1 列 (1,2) 和第 2 列 (1,2,3)
  • 稍微修改了问题
  • 为什么不能在连接的列上选择不同的?
  • 不,我需要 150.columns 中的每一个中的不同值,并且在组合列中不是唯一的。

标签: sql database oracle plsql


【解决方案1】:

从我的角度来看,目标布局是错误的。是的,您可以做到这一点 - 一个接一个地显示 150 列,每列只有不同的值。但是,这很难维护,您必须编写大量代码。

因此,另一个适合 A5 纸张大小的建议(或更小,如果您使用较小的字体:))。 “我的”目标表只包含两列,成对的列名本身及其不同的值。为此,让 Oracle 通过为您编写查询来完成其中的困难部分。如何?通过动态 SQL。

我的示例基于 Scott 的 EMP 表。我正在显示正在运行的命令,以便您查看实际执行的内容;你不必那样做。另外,我的value 列的数据类型是varchar2,这意味着我依靠Oracle 的能力来隐式地将不同的数据类型转换为它。适用于我的简单测试用例。如果它不适合你,那就倒霉了——你将不得不付出更多的努力。

好了,废话不多说,开始工作吧。

目标表:

SQL> create table target
  2    (column_name varchar2(30),
  3     value       varchar2(50)
  4    );

Table created.

样本数据(代表你的150-columns-table):

SQL> select * from emp order by deptno;

     EMPNO ENAME      JOB              MGR HIREDATE          SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ---------- ---------- ---------- ----------
      7782 CLARK      MANAGER         7839 09.06.1981       2450                    10
      7839 KING       PRESIDENT            17.11.1981       5000                    10
      7934 MILLER     CLERK           7782 23.01.1982       1300                    10
      7566 JONES      MANAGER         7839 02.04.1981       2975                    20
      7902 FORD       ANALYST         7566 03.12.1981       3000                    20
      7876 ADAMS      CLERK           7788 12.01.1983       1100                    20
      7369 SMITH      CLERK           7902 17.12.1980        800                    20
      7788 SCOTT      ANALYST         7566 09.12.1982       3000                    20
      7521 WARD       SALESMAN        7698 22.02.1981       1250        500         30
      7844 TURNER     SALESMAN        7698 08.09.1981       1500          0         30
      7499 ALLEN      SALESMAN        7698 20.02.1981       1600        300         30
      7900 JAMES      CLERK           7698 03.12.1981        950                    30
      7698 BLAKE      MANAGER         7839 01.05.1981       2850                    30
      7654 MARTIN     SALESMAN        7698 28.09.1981       1250       1400         30

14 rows selected.

程序:

SQL> set serveroutput on;
SQL> declare
  2    l_str varchar2(200);
  3  begin
  4    for cur_r in (select column_name
  5                  from user_tab_columns
  6                  where table_name = 'EMP'
  7                  order by column_id
  8                 )
  9    loop
 10      l_str := 'insert into target (column_name, value) ' ||
 11               'select distinct ' || chr(39) || cur_r.column_name || chr(39) ||
 12                              ', '|| cur_r.column_name || ' from emp';
 13      dbms_output.put_line(l_str);
 14      execute immediate l_str;
 15    end loop;
 16  end;
 17  /
insert into target (column_name, value) select distinct 'EMPNO', EMPNO from emp
insert into target (column_name, value) select distinct 'ENAME', ENAME from emp
insert into target (column_name, value) select distinct 'JOB', JOB from emp
insert into target (column_name, value) select distinct 'MGR', MGR from emp
insert into target (column_name, value) select distinct 'HIREDATE', HIREDATE from emp
insert into target (column_name, value) select distinct 'SAL', SAL from emp
insert into target (column_name, value) select distinct 'COMM', COMM from emp
insert into target (column_name, value) select distinct 'DEPTNO', DEPTNO from emp

PL/SQL procedure successfully completed.

结果:

SQL> select * From target order by column_name, value;

COLUMN_NAME                    VALUE
------------------------------ -----------------------------
COMM                           0
COMM                           1400
COMM                           300
COMM                           500
COMM
DEPTNO                         10          --> true; there are only 3 different
DEPTNO                         20          --  departments: 
DEPTNO                         30          --  10, 20 and 30
<snip>
JOB                            ANALYST     --> the same goes for jobs - this is
JOB                            CLERK       --  a list of distinct jobs
JOB                            MANAGER     --  in the EMP table
JOB                            PRESIDENT
JOB                            SALESMAN
<snip>

因此,如果您想知道这些列中的不同值,您只需

SQL> select value
  2  from target
  3  where column_name = 'JOB';

VALUE
-------------------------------------
ANALYST
PRESIDENT
CLERK
SALESMAN
MANAGER

SQL>

就这么简单。

【讨论】:

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