oracle 根据某一行的值转化成列?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle 根据某一行的值转化成列?相关的知识,希望对你有一定的参考价值。

假如:表结构如下:字段
name zfname date
甲 size1 2010-2-1
甲 size2 2010-2-1
乙 size1 2010-2-1
丙 size3 2010-2-1 。。。
我想要的效果是,根据 zfname 字段转列(这个字段有多少个不一样的值,就转多少列)
所以要的就是如下效果
name size1 size2 size3 ...(因为我的数据只有这三个,所以就转三列)
甲 1 1 0
乙 1 0 0
丙 0 0 1
也就说,转好后再统计 ,转的列名 就是zfname 字段 所存的数据
大家能否写个sql 语句给我啊 ,谢谢啊

参考技术A 楼主这种 典型的行列转换问题。

Oracle 一般就通过 DECODE 或者 CASE WHEN 来处理。

SQL> CREATE TABLE TEST_YLX (
2 name VARCHAR2(2),
3 zfname VARCHAR2(6),
4 tdate DATE
5 );

Table created.

SQL>
SQL> INSERT INTO TEST_YLX VALUES ('A', 'size1', TO_DATE('2010-02-01', 'YYYY-MM-D
D') );

1 row created.

SQL> INSERT INTO TEST_YLX VALUES ('A', 'size2', TO_DATE('2010-02-01', 'YYYY-MM-D
D') );

1 row created.

SQL> INSERT INTO TEST_YLX VALUES ('B', 'size1', TO_DATE('2010-02-01', 'YYYY-MM-D
D') );

1 row created.

SQL> INSERT INTO TEST_YLX VALUES ('C', 'size3', TO_DATE('2010-02-01', 'YYYY-MM-D
D') );

1 row created.

SQL>
SQL> SELECT
2 name,
3 SUM ( DECODE(zfname, 'size1', 1, 0) ) AS size1,
4 SUM ( DECODE(zfname, 'size2', 1, 0) ) AS size2,
5 SUM ( CASE WHEN(zfname = 'size3') THEN 1
6 ELSE 0
7 END
8 ) AS size3
9 FROM
10 test_ylx
11 GROUP BY
12 name;

NAME SIZE1 SIZE2 SIZE3
---- ---------- ---------- ----------
A 1 1 0
B 1 0 0
C 0 0 1

SQL>

上面的例子中, size1 和 size2 是用 DECODE
size3 用 CASE WHEN

看具体情况需要,而使用。

========================================

唯一麻烦的是

这个SQL, 需要预先知道, size1 size2 size3 这些信息

如果表中新增加了 size4 , 需要修改 SQL 语句。
参考技术B 典型的分类汇总

oracle 有个 decode(列传行)函数
参考技术C select name,sum(decode(zfname,'size1',1,0)) size1
,sum(decode(zfname,'size2',1,0)) size2
,sum(decode(zfname,'size3',1,0)) size3
from 表
group by name本回答被提问者采纳
参考技术D 你知道有具体多少个zfname 数值,可以用一条语句,要不就要用存储过程了

mysql中生成列与JSON类型的索引

MySQL中支持生成列,生成列的值是根据列定义中包含的表达式计算的。

一个简单的例子来认识生成列!

CREATE TABLE triangle(
sidea DOUBLE,
sideb DOUBLE,
sidec DOUBLE AS (SQRT(sidea * sidea + sideb * sideb))
);

INSERT INTO triangle(sidea, sideb)  VALUES(3,4),(6,8),(5,12);

mysql> select * from triangle;  #插入数值的时候并没有插入c的值,但是查询的时候,还是有了c值
+-------+-------+-------+
| sidea | sideb | sidec |
+-------+-------+-------+
|     3 |     4 |     5 |
|     6 |     8 |    10 |
|     5 |    12 |    13 |
+-------+-------+-------+
3 rows in set (0.00 sec)

mysql>

生成列中的值,是根据生成列的定义计算出来的

生成列的定义如下:

col_name data_type [GENERATED ALWAYS] AS (expression)
  [VIRTUAL | STORED] [NOT NULL | NULL]
  [UNIQUE [KEY]] [[PRIMARY] KEY]
  [COMMENT ‘string‘]
#AS表达式表示生成列并用于计算生成列的表达式。As之前的GENERATED ALWAYS可以让生成列的性质更明确(应该没什么作用,反正是可以省略的)!
#VIRTUAL | STORED 关键字表示列值的存储方式
  • VIRTUAL: 不存储列值,但在读取值之前立即计算此列的数值,虚拟列不占存储空间,innodb支持虚拟列上的二级索引。为默认的存储方式。
  •   STORED:插入或更新时,将计算存储列的值,并且占用存储空间。
 生成列的表达式必须遵循以下的规则,否则会报错:
  1. 允许使用字符串,运算符和确定性内置函数。对于给定的相同的数据库,不同连接的用户调用会产生相同的结果,则这个函数时确定的。now()函数就不是确定性函数。
  2. 不允许使用子查询,参数,变量,存储函数(stored functions)和用户自定义的函数。
  3. 生成的列定义可以引用其他生成的列,但只能引用表定义中较早出现的列。生成的列定义可以引用表中的任何基本(非生成)列,无论其定义是早期还是稍后发生
  4. auto_increment属性不能再生成列的定义中使用。
  5. 一个AUTO_INCREMENT列不能用作在生成的列定义的基柱(An AUTO_INCREMENT column cannot be used as a base column in a generated column definition.)
  6. 从MySQL 5.7.10开始,如果表达式求值导致截断或向函数提供不正确的输入,则 CREATE TABLE语句将以错误终止并拒绝DDL操作

 生成列的作用(可能不太准确):

  • 虚拟生成的列可用作简化和统一查询的方法。可以将复杂条件定义为生成列,并从表上的多个查询引用,以确保他们全部使用完全相同的条件。
  • 存储生成的列可以用作物化缓存,用于复杂的条件,这些条件在运行中计算成本很高。
  • 生成列可以模拟功能索引,利用生成列定义功能表达式对其进行索引。例如对JSON数据类型。对于存储的生成列,这种方法缺点是存储两次,一次是生成列的值,另一次是索引。
  • 如果生成的列已编制索引,则优化程序将识别与列定义匹配的查询表达式,并在查询执行期间根据需要使用列中的索引,即使查询未按名称直接引用该列也是如此。

如下一个含有json类型字段的表:

CREATE TABLE json_test (
    id INT auto_increment PRIMARY KEY,
    userinfo json
);

#插入数据

INSERT INTO json_test(userinfo) VALUES({"name":"libai","address":"china","email":"[email protected]"});
INSERT INTO json_test(userinfo) VALUES({"name":"obama","address":"miguo","email":"[email protected]"});
INSERT INTO json_test(userinfo) VALUES({"name":"putin","address":"russia","email":"[email protected]"});

#

给表中添加生成列

alter table json_test add column user_name varchar(40) generated always  as (userinfo->"$.name") virtual;

#查看表中的数据
mysql> select * from json_test;
+----+--------------------------------------------------------------------+-----------+
| id | userinfo                                                           | user_name |
+----+--------------------------------------------------------------------+-----------+
|  1 | {"name": "libai", "email": "libai@163.com", "address": "china"}    | "libai"   |
|  2 | {"name": "obama", "email": "libai@gmail.com", "address": "miguo"}  | "obama"   |
|  3 | {"name": "putin", "email": "putin@gmail.com", "address": "russia"} | "putin"   |
+----+--------------------------------------------------------------------+-----------+
3 rows in set (0.00 sec)

#在表中插入数据user_name列的数值会自动计算,这时候,我们就可以对user_name列添加索引!

 




以上是关于oracle 根据某一行的值转化成列?的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中把一个set转化成另外一个list的名称?

SQL 如何把一列的值转换成一行显示

将行反透视成列

sql 一列拼接成一行,再分割成列

pandas取列值转化为列表

mysql中生成列与JSON类型的索引