Solución:
No me queda claro qué es una “forma más elegante”.
Oracle puede usar la siguiente declaración para convertir columnas en filas
select all_name from foo unpivot (all_name for col_name in ( his_name, her_name, other_name));
Este es el diagrama de sintaxis de la instrucción select
SELECT [ALL | DISTINCT | DISTINCTROW ] [HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] select_expr [, select_expr ...] [FROM table_references [PARTITION partition_list] [WHERE where_condition] [GROUP BY col_name [ASC | DESC], ... [WITH ROLLUP]] [HAVING where_condition] [ORDER BY position [ASC | DESC], ...] [LIMIT row_count OFFSET offset] [PROCEDURE procedure_name(argument_list)] [INTO OUTFILE 'file_name' [CHARACTER SET charset_name] export_options | INTO DUMPFILE 'file_name' | INTO var_name [, var_name]] [FOR UPDATE | LOCK IN SHARE MODE]]
Ni el WHERE
,GROUP BY
, HAVING
, LIMIT
, SELECT
, INTO
, FOR UPDATE
ni el LOCK IN SHARE MODE
La cláusula puede aumentar el número de filas definidas por el FROM
cláusula. Así que si table_references
es igual a foo
la consulta no puede contener más filas que la tabla foo
.
Entonces MySQL no tiene una forma tan “elegante” de desvincular una tabla.
Una forma de realizar tal desvinculación sin el uso de UNION se puede hacer mediante la compra mediante una combinación. Queremos crear 3 filas para cada fila del foo
tabla, por lo que creamos una tabla auxiliar que contiene tres filas y (cruz) unimos a la foo
mesa. Ahora tenemos tres filas en nuestra consulta para cada fila en la tabla base foo
. Cada fila de consulta se puede completar con los datos adecuados. En su lugar, la función ELT se puede utilizar IF o CASE.
Violín SQL
Configuración del esquema de 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);
Consulta dinámica:
select elt(aux.line,foo.his_name,foo.her_name,foo.other_name) all_name
from foo cross join aux
Resultados:
| all_name |
|----------|
| one |
| four |
| two |
| five |
| three |
| six |
Por supuesto, hay diferentes formas de crear una tabla que contenga las tres filas con valores 1,2,3:
Violín SQL
Usando una mesa auxiliar:
create table aux(line int);
insert into aux(line) values(1);
insert into aux(line) values(2);
insert into aux(line) values(3);
Usando una mesa auxiliar:
select line
from aux
usando una expresión constante:
select 1 line
union all
select 2
union all
select 3
contando números de fila: Lo encontré aquí
SELECT
@rownum := @rownum + 1 line
FROM
(SELECT @rownum := 0) r, INFORMATION_SCHEMA.COLUMNS t
where @rownum<3
usando una de las vistas del diccionario:
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
Resultados:
| ORDINAL_POSITION |
|------------------|
| 1 |
| 2 |
| 3 |
UTILIZANDO UNION
Otros han enviado respuestas intentando la agregación para recopilar datos sin usar UNION
May 12, 2014
: Mejoras de consultas sin UNIONMay 05, 2015
: Calcular valores de tres tablas relacionadas, sin usar join o unionFeb 20, 2012
: Agregación de datos SQL
En este caso, lo que hace UNION
una necesidad absoluta es la fusión de tres columnas en una sola columna. Nada podría ser más elegante que usar UNION
SELECT her_name AS name FROM foo
UNION
SELECT his_name AS name FROM foo
UNION
SELECT other_name AS name FROM foo;
Esto produciría una lista distinta de nombres.
Si la intención es seleccionar algunas columnas y generar una lista de una sola columna de los valores distintos, entonces se necesita SQL dinámico para producir dicha consulta. Para este ejemplo, supongamos lo siguiente
mydb
esquema- mesa llamada
foo
- columnas para seleccionar juntas
her_name
his_name
other_name
Aquí está el SQL dinámico para generar la misma consulta
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 @sqlG
PREPARE s FROM @sql;
EXECUTE s;
DEALLOCATE PREPEARE s;
los SELECT @sqlG
te dejará ver el SQL generado
Sin programar formalmente un procedimiento almacenado, esto es lo mejor que se puede conseguir.
SIN UTILIZAR UNION
Si el objetivo es estrictamente no usar UNION
, necesitas una tabla temporal con 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;
MIRA MAMÁ, SIN UNIÓN !!!
Una semi-solución: estarán en columna. (Pero también están en una sola fila, más o menos).
SELECT CONCAT_WS("n", her_name, his_name, other_name) AS name FROM foo
Por ejemplo:
mysql> SELECT CONCAT_WS("n", province) FROM Provinces;
+---------------------------+
| CONCAT_WS("n", province) |
+---------------------------+
| Alberta |
| British Columbia |
| Manitoba |
| New Brunswick |
| Newfoundland and Labrador |
| Nova Scotia |
...
Si va a una página web, considere "
en lugar de
""n"
.