我有一个包含几列的表格,我想要SELECT
:
SELECT his_name , her_name, other_name FROM foo;
Run Code Online (Sandbox Code Playgroud)
但是,我想将所有结果合并到一个列中。举个例子,我可以做到这一点UNION ALL
的
SELECT her_name AS name FROM foo
UNION ALL
SELECT his_name AS name FROM foo
UNION ALL
SELECT other_name AS name FROM foo
Run Code Online (Sandbox Code Playgroud)
有没有更优雅的方法来做这个操作?
mir*_*173 12
我不清楚什么是“更优雅的方式”。
Oracle 可以使用以下语句将列变为行
选择 all_name 来自 foo unpivot (all_name for col_name in ( 他的名字, 她的名字, 其他名字));
这是select语句的语法图
选择 [所有 | 独特 | 区别] [高优先级] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] select_expr [, select_expr ...] [来自 table_references [PARTITION partition_list] [WHERE where_condition] [GROUP BY {col_name | 表达式 | 位置} [ASC | DESC], ... [汇总]] [有 where_condition] [ORDER BY {col_name | 表达式 | 位置} [ASC | DESC], ...] [LIMIT {[offset,] row_count | row_count OFFSET 偏移量}] [PROCEDURE procedure_name(argument_list)] [进入 OUTFILE 'file_name' [字符集 charset_name] 出口选项 | INTO DUMPFILE '文件名' | INTO var_name [, var_name]] [更新| 锁定共享模式]]
无论是WHERE
,GROUP BY
,HAVING
,LIMIT
,SELECT
,INTO
,FOR UPDATE
也不LOCK IN SHARE MODE
子句可以增加由定义的行数FROM
子句。所以如果table_references
等于foo
查询不能包含比表更多的行foo
。
所以 MySQL 没有这种“优雅”的方式来反透视表。
一种无需使用 UNION 即可完成这种逆透视的方法可以使用 join 来完成。我们想为foo
表的每一行创建 3 行,因此我们创建了一个包含三行的辅助表并将其(交叉)连接到foo
表中。现在,对于基表中的每一行,我们的查询中有三行foo
。每个查询行都可以由适当的数据填充。相反,ELT 函数可以使用 IF 或 CASE。
MySQL 5.6 架构设置:
create table foo (
his_name varchar(10),
her_name varchar(10),
other_name varchar(10));
insert into foo(his_name,her_name,other_name) values ('one','two','three');
insert into foo(his_name,her_name,other_name) values ('four','five','six');
create table aux(line int);
insert into aux(line) values(1);
insert into aux(line) values(2);
insert into aux(line) values(3);
Run Code Online (Sandbox Code Playgroud)
枢轴查询:
select elt(aux.line,foo.his_name,foo.her_name,foo.other_name) all_name
from foo cross join aux
Run Code Online (Sandbox Code Playgroud)
结果:
| all_name |
|----------|
| one |
| four |
| two |
| five |
| three |
| six |
Run Code Online (Sandbox Code Playgroud)
当然,有多种方法可以创建包含值为 1、2、3 的三行的表:
使用辅助表:
create table aux(line int);
insert into aux(line) values(1);
insert into aux(line) values(2);
insert into aux(line) values(3);
Run Code Online (Sandbox Code Playgroud)
使用辅助表:
select line
from aux
Run Code Online (Sandbox Code Playgroud)
使用常量表达式:
select 1 line
union all
select 2
union all
select 3
Run Code Online (Sandbox Code Playgroud)
SELECT
@rownum := @rownum + 1 line
FROM
(SELECT @rownum := 0) r, INFORMATION_SCHEMA.COLUMNS t
where @rownum<3
Run Code Online (Sandbox Code Playgroud)
使用字典视图之一:
SELECT
ordinal_position line
from INFORMATION_SCHEMA.COLUMNS t
where table_catalog='def'
and table_schema='information_schema'
and table_name='COLUMNS'
and ordinal_position between 1 and 3
Run Code Online (Sandbox Code Playgroud)
结果:
| ORDINAL_POSITION |
|------------------|
| 1 |
| 2 |
| 3 |
Run Code Online (Sandbox Code Playgroud)
Rol*_*DBA 11
其他人提交了答案,尝试聚合以收集数据而不使用 UNION
May 12, 2014
:没有 UNION 的查询改进May 05, 2015
:从三个相关表计算值,不使用连接或联合Feb 20, 2012
: SQL 数据聚合在这种情况下,UNION
绝对必须的是将三列合并为一列。没有比使用更优雅的了UNION
SELECT her_name AS name FROM foo
UNION
SELECT his_name AS name FROM foo
UNION
SELECT other_name AS name FROM foo;
Run Code Online (Sandbox Code Playgroud)
这将产生一个不同的名称列表。
如果目的是选择一些列并生成不同值的单列列表,则需要动态 SQL 来生成这样的查询。对于这个例子,让我们假设以下
mydb
模式foo
her_name
his_name
other_name
这是生成相同查询的动态 SQL
USE mydb
SET group_concat_max_len = 1048576;
SELECT GROUP_CONCAT(
CONCAT('SELECT ',column_name,' AS name FROM ',table_name)
SEPARATOR ' UNION ')
INTO @sql
FROM information_schema.tables
WHERE table_schema=DATABASE() AND table_name='foo' AND column_name IN
('her_name','his_name','other_name');
SELECT @sql\G
PREPARE s FROM @sql;
EXECUTE s;
DEALLOCATE PREPEARE s;
Run Code Online (Sandbox Code Playgroud)
该SELECT @sql\G
将让你看到生成的SQL
如果没有正式编写存储过程的脚本,这将是最好的。
如果目标是严格不使用UNION
,则需要一个带有以下内容的临时表PRIMARY KEY
:
CREATE TABLE names SELECT her_name name FROM foo WHERE 1=2;
ALTER TABLE names ADD PRIMARY KEY (name);
INSERT IGNORE INTO names (name) SELECT her_name FROM foo;
INSERT IGNORE INTO names (name) SELECT his_name FROM foo;
INSERT IGNORE INTO names (name) SELECT other_name FROM foo;
SELECT * FROM names;
DROP TABLE names;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
138294 次 |
最近记录: |