

 Amazon Redshift dejará de admitir la creación de nuevas UDF de Python a partir del parche 198. Las UDF de Python existentes seguirán funcionando hasta el 30 de junio de 2026. Para obtener más información, consulte la [publicación del blog](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/). 

# Cláusula FROM
<a name="r_FROM_clause30"></a>

La cláusula FROM en una consulta enumera las referencias de la tabla (tablas, vistas y subconsultas) desde las que se seleccionan los datos. Si se enumeran varias referencias de tabla, se deben combinar las tablas a través de la sintaxis adecuada en la cláusula FROM o en la cláusula WHERE. Si no se especifican criterios de combinación, el sistema procesa la consulta como una combinación cruzada (producto cartesiano). 

**Topics**
+ [Sintaxis](#r_FROM_clause30-synopsis)
+ [Parameters](#r_FROM_clause30-parameters)
+ [Notas de uso](#r_FROM_clause_usage_notes)
+ [Ejemplos de PIVOT y UNPIVOT](r_FROM_clause-pivot-unpivot-examples.md)
+ [Ejemplos de JOIN](r_Join_examples.md)
+ [Ejemplos de UNNEST](r_FROM_clause-unnest-examples.md)

## Sintaxis
<a name="r_FROM_clause30-synopsis"></a>

```
FROM table_reference [, ...]
```

donde *table\$1reference* es uno de los siguientes: 

```
with_subquery_table_name [ table_alias ]
table_name [ * ] [ table_alias ]
( subquery ) [ table_alias ]
table_reference [ NATURAL ] join_type table_reference
   [ ON join_condition | USING ( join_column [, ...] ) ]
table_reference  join_type super_expression 
   [ ON join_condition ]
table_reference PIVOT ( 
   aggregate(expr) [ [ AS ] aggregate_alias ]
   FOR column_name IN ( expression [ AS ] in_alias [, ...] )
) [ table_alias ]
table_reference UNPIVOT [ INCLUDE NULLS | EXCLUDE NULLS ] ( 
   value_column_name 
   FOR name_column_name IN ( column_reference [ [ AS ]
   in_alias ] [, ...] )
) [ table_alias ]
UNPIVOT expression AS value_alias [ AT attribute_alias ]
( super_expression.attribute_name ) AS value_alias [ AT index_alias ]
UNNEST ( column_reference )
  [AS] table_alias ( unnested_column_name )
UNNEST ( column_reference ) WITH OFFSET
  [AS] table_alias ( unnested_column_name, [offset_column_name] )
```

El *table\$1alias* opcional se puede usar para dar nombres temporales a tablas y referencias de tablas complejas y, si se desea, también a sus columnas, como se muestra a continuación: 

```
[ AS ] alias [ ( column_alias [, ...] ) ]
```

## Parameters
<a name="r_FROM_clause30-parameters"></a>

 *with\$1subquery\$1table\$1name*   
Una tabla definida por una subconsulta en la [Cláusula WITH](r_WITH_clause.md). 

 *table\$1name*   
Nombre de una tabla o vista. 

 *alias*   
Nombre alternativo temporal para una tabla o vista. Se debe proporcionar un alias para una tabla obtenida de una subconsulta. En otras referencias de tabla, los alias son opcionales La palabra clave AS es siempre opcional. Los alias de la tabla brindan un acceso directo para identificar tablas en otras partes de una consulta, como la cláusula WHERE. Por ejemplo:   

```
select * from sales s, listing l
where s.listid=l.listid
```

 *column\$1alias*   
Nombre alternativo temporal para una columna en una tabla o vista. 

 *subquery*   
Una expresión de consulta que toma el valor de una tabla. La tabla solo existe mientras dura la consulta y, por lo general, se le asigna un nombre o un *alias*. No obstante, no es obligatorio tener un alias. También puede definir nombres de columnas para tablas que derivan de subconsultas. Designar un nombre a los alias de las columnas es importante cuando desea combinar los resultados de las subconsultas con otras tablas y cuando desea seleccionar o limitar esas columnas en otros sitios de la consulta.   
Una subconsulta puede contener una cláusula ORDER BY, pero es posible que esta cláusula no tenga ningún efecto si no se especifica también una cláusula OFFSET o LIMIT. 

NATURAL   
Define una combinación que utiliza automáticamente todos los pares de columnas con nombres idénticos en las dos tablas como las columnas de combinación. No se requiere una condición de combinación explícita. Por ejemplo, si las tablas CATEGORY y EVENT tienen columnas denominadas CATID, una combinación natural de estas tablas es una combinación de las columnas CATID.   
Si se especifica una combinación NATURAL, pero no existen pares de columnas con nombres idénticos en las tablas que deben combinarse, la consulta se establece en una combinación cruzada. 

 *join\$1type*   
Especifique uno de los siguientes tipos de combinación:   
+ [INNER] JOIN 
+ LEFT [OUTER] JOIN 
+ RIGHT [OUTER] JOIN 
+ FULL [OUTER] JOIN 
+ CROSS JOIN 
Las combinaciones cruzadas son combinaciones no calificadas; devuelven el producto cartesiano de dos tablas.   
Las combinaciones internas y externas son combinaciones calificadas. Están calificadas implícitamente (en combinaciones naturales), con la sintaxis ON o USING en la cláusula FROM, o con una condición WHERE.   
Una combinación interna devuelve filas coincidentes únicamente en función a la condición de combinación o a la lista de columnas de combinación. Una combinación externa devuelve todas las filas que la combinación interna equivalente devolvería, además de filas no coincidentes de la tabla "izquierda", tabla "derecha" o ambas tablas. La tabla izquierda es la primera tabla de la lista, y la tabla derecha es la segunda tabla de la lista. Las filas no coincidentes contienen valores NULL para llenar el vacío de las columnas de salida. 

ON *join\$1condition*   
Especificación del tipo de combinación donde las columnas de combinación se establecen como una condición que sigue la palabra clave ON. Por ejemplo:   

```
sales join listing
on sales.listid=listing.listid and sales.eventid=listing.eventid
```

USING ( *join\$1column* [, ...] )   
Especificación del tipo de combinación donde las columnas de combinación aparecen enumeradas entre paréntesis. Si se especifican varias columnas de combinación, se delimitan por comas. La palabra clave USING debe preceder a la lista. Por ejemplo:   

```
sales join listing
using (listid,eventid)
```

PIVOT  
Rota la salida de filas a columnas, con el fin de representar datos tabulares en un formato fácil de leer. La salida se representa horizontalmente en varias columnas. PIVOT es similar a una consulta GROUP BY con una agregación, utilizando una expresión de agregación para especificar un formato de salida. No obstante, a diferencia de GROUP BY, los resultados se devuelven en columnas en lugar de filas.  
Para ver ejemplos que muestran cómo realizar consultas con PIVOT y UNPIVOT, consulte [Ejemplos de PIVOT y UNPIVOT](r_FROM_clause-pivot-unpivot-examples.md).

UNPIVOT  
*Rotación de columnas en filas con UNPIVOT*: el operador transforma las columnas de resultados, de una tabla de entrada o resultados de consultas, en filas, para facilitar la lectura de la salida. UNPIVOT combina los datos de sus columnas de entrada en dos columnas de resultados: una columna de nombres y una columna de valores. La columna de nombres contiene nombres de columna de la entrada, como entradas de fila. La columna de valores contiene valores de las columnas de entrada, como los resultados de una agregación. Por ejemplo, el recuento de elementos de varias categorías.  
*Anulación de la dinamización de objetos con UNPIVOT (SUPER)*: puede realizar una anulación de la dinamización de objetos, donde la *expresión* es una expresión SUPER que hace referencia a otro elemento de la cláusula FROM. Para obtener más información, consulte [Anulación de la dinamización de los objetos](query-super.md#unpivoting). Tiene también ejemplos que muestran cómo realizar consultas de datos semiestructurados, como datos con formato JSON.

*super\$1expression*  
Una expresión SUPER válida. Amazon Redshift devuelve una fila para cada valor del atributo especificado. Para obtener más información acerca del tipo de datos SUPER, consulte [Tipo SUPER](r_SUPER_type.md). Para obtener más información sobre los valores SUPER no anidados, consulte [Consultas de eliminación del anidamiento](query-super.md#unnest).

*attribute\$1name*  
El nombre de un atributo de la expresión SUPER.

*index\$1alias*  
Alias del índice que indica la posición del valor en la expresión SUPER.

UNNEST  
Expande una estructura anidada, normalmente una matriz SUPER, en columnas que contienen los elementos no anidados. Para obtener más información sobre cómo eliminar el anidamiento de datos SUPER, consulte [Consulta de datos semiestructurados](query-super.md). Para ver ejemplos, consulte [Ejemplos de UNNEST](r_FROM_clause-unnest-examples.md). 

*unnested\$1column\$1name*  
Nombre de la columna que contiene los elementos no anidados. 

UNNEST … WITH OFFSET  
Agrega una columna de desplazamiento a la salida no anidada, donde el desplazamiento representa el índice basado en cero de cada elemento de la matriz. Esta variante es útil cuando se desea ver la posición de los elementos en una matriz. Para obtener más información sobre cómo eliminar el anidamiento de datos SUPER, consulte [Consulta de datos semiestructurados](query-super.md). Para ver ejemplos, consulte [Ejemplos de UNNEST](r_FROM_clause-unnest-examples.md). 

*offset\$1column\$1name*  
Un nombre personalizado para la columna de desplazamiento que le permite definir explícitamente cómo aparecerá la columna de índice en la salida. Este parámetro es opcional. De forma predeterminada, el nombre de la columna de desplazamiento es `offset_col`. 

## Notas de uso
<a name="r_FROM_clause_usage_notes"></a>

Las columnas de combinación deben tener tipos de datos comparables. 

Una combinación NATURAL o USING retiene solo uno de cada par de columnas de combinación en el conjunto de resultados intermedios. 

Una combinación con la sintaxis ON retiene ambas columnas de combinación en su conjunto de resultados intermedios. 

Consulte también [Cláusula WITH](r_WITH_clause.md). 

# Ejemplos de PIVOT y UNPIVOT
<a name="r_FROM_clause-pivot-unpivot-examples"></a>

PIVOT y UNPIVOT son parámetros de la cláusula FROM que alternan la salida de la consulta de filas a columnas y de columnas a filas, respectivamente. Representan resultados de consultas tabulares en un formato fácil de leer. En los siguientes ejemplos se utilizan datos y consultas de prueba para mostrar cómo utilizarlos.

Para obtener más información sobre estos parámetros y sus opciones predeterminadas, consulte [Cláusula FROM](https://docs.aws.amazon.com/redshift/latest/dg/r_FROM_clause30.html).

## Ejemplos de PIVOT
<a name="r_FROM_clause-pivot-examples"></a>

Configure la tabla y los datos de muestra y utilícelos para ejecutar las consultas de ejemplo posteriores.

```
CREATE TABLE part (
    partname varchar,
    manufacturer varchar,
    quality int,
    price decimal(12, 2)
);

INSERT INTO part VALUES ('prop', 'local parts co', 2, 10.00);
INSERT INTO part VALUES ('prop', 'big parts co', NULL, 9.00);
INSERT INTO part VALUES ('prop', 'small parts co', 1, 12.00);

INSERT INTO part VALUES ('rudder', 'local parts co', 1, 2.50);
INSERT INTO part VALUES ('rudder', 'big parts co', 2, 3.75);
INSERT INTO part VALUES ('rudder', 'small parts co', NULL, 1.90);

INSERT INTO part VALUES ('wing', 'local parts co', NULL, 7.50);
INSERT INTO part VALUES ('wing', 'big parts co', 1, 15.20);
INSERT INTO part VALUES ('wing', 'small parts co', NULL, 11.80);
```

PIVOT en `partname` con una agregación `AVG` en `price`.

```
SELECT *
FROM (SELECT partname, price FROM part) PIVOT (
    AVG(price) FOR partname IN ('prop', 'rudder', 'wing')
);
```

La consulta genera el siguiente resultado.

```
  prop   |  rudder  |  wing
---------+----------+---------
 10.33   | 2.71     | 11.50
```

En el ejemplo anterior, los resultados se transforman en columnas. En el siguiente ejemplo se muestra una consulta de `GROUP BY` que devuelve los precios promedio en filas, en lugar de hacerlo en columnas.

```
SELECT partname, avg(price)
FROM (SELECT partname, price FROM part)
WHERE partname IN ('prop', 'rudder', 'wing')
GROUP BY partname;
```

La consulta genera el siguiente resultado.

```
 partname |  avg
----------+-------
 prop     | 10.33
 rudder   |  2.71
 wing     | 11.50
```

Un ejemplo de `PIVOT` con `manufacturer` como columna implícita.

```
SELECT *
FROM (SELECT quality, manufacturer FROM part) PIVOT (
    count(*) FOR quality IN (1, 2, NULL)
);
```

La consulta genera el siguiente resultado.

```
 manufacturer      | 1  | 2  | null
-------------------+----+----+------
 local parts co    | 1  | 1  |  1
 big parts co      | 1  | 1  |  1
 small parts co    | 1  | 0  |  2
```

 Columnas de tabla de entrada a las que no se hace referencia en la definición de `PIVOT` se agregan implícitamente a la tabla de resultados. Este es el caso de la columna `manufacturer` del ejemplo anterior. En el ejemplo también se muestra que `NULL` es un valor válido para el operador `IN`. 

`PIVOT` en el ejemplo anterior devuelve información similar a la siguiente consulta, lo que incluye `GROUP BY`. La diferencia es que `PIVOT` devuelve el valor `0` para la columna `2` y el fabricante `small parts co`. La consulta `GROUP BY` no contiene una fila correspondiente. En la mayoría de los casos, `PIVOT` inserta `NULL` si una fila no tiene datos de entrada para una columna determinada. No obstante, el agregado de recuento no devuelve `NULL` y `0` es el valor predeterminado.

```
SELECT manufacturer, quality, count(*)
FROM (SELECT quality, manufacturer FROM part)
WHERE quality IN (1, 2) OR quality IS NULL
GROUP BY manufacturer, quality
ORDER BY manufacturer;
```

La consulta genera el siguiente resultado.

```
 manufacturer        | quality | count
---------------------+---------+-------
 big parts co        |         |     1
 big parts co        |       2 |     1
 big parts co        |       1 |     1
 local parts co      |       2 |     1
 local parts co      |       1 |     1
 local parts co      |         |     1
 small parts co      |       1 |     1
 small parts co      |         |     2
```

 El operador PIVOT acepta alias opcionales en la expresión agregada y en cada valor para el operador `IN`. Utilice alias para personalizar los nombres de las columnas. Si no hay alias agregados, solo se utilizan alias de la lista `IN`. De lo contrario, el alias agregado se agrega al nombre de la columna con un guion bajo para separar los nombres. 

```
SELECT *
FROM (SELECT quality, manufacturer FROM part) PIVOT (
    count(*) AS count FOR quality IN (1 AS high, 2 AS low, NULL AS na)
);
```

La consulta genera el siguiente resultado.

```
 manufacturer      | high_count  | low_count | na_count
-------------------+-------------+-----------+----------
 local parts co    |           1 |         1 |        1
 big parts co      |           1 |         1 |        1
 small parts co    |           1 |         0 |        2
```

Configure la tabla y los datos de muestra siguientes y utilícelos para ejecutar las consultas de ejemplo posteriores. Los datos representan las fechas de reserva de una colección de hoteles.

```
CREATE TABLE bookings (
    booking_id int,
    hotel_code char(8),
    booking_date date,
    price decimal(12, 2)
);

INSERT INTO bookings VALUES (1, 'FOREST_L', '02/01/2023', 75.12);
INSERT INTO bookings VALUES (2, 'FOREST_L', '02/02/2023', 75.00);
INSERT INTO bookings VALUES (3, 'FOREST_L', '02/04/2023', 85.54);

INSERT INTO bookings VALUES (4, 'FOREST_L', '02/08/2023', 75.00);
INSERT INTO bookings VALUES (5, 'FOREST_L', '02/11/2023', 75.00);
INSERT INTO bookings VALUES (6, 'FOREST_L', '02/14/2023', 90.00);

INSERT INTO bookings VALUES (7, 'FOREST_L', '02/21/2023', 60.00);
INSERT INTO bookings VALUES (8, 'FOREST_L', '02/22/2023', 85.00);
INSERT INTO bookings VALUES (9, 'FOREST_L', '02/27/2023', 90.00);

INSERT INTO bookings VALUES (10, 'DESERT_S', '02/01/2023', 98.00);
INSERT INTO bookings VALUES (11, 'DESERT_S', '02/02/2023', 75.00);
INSERT INTO bookings VALUES (12, 'DESERT_S', '02/04/2023', 85.00);

INSERT INTO bookings VALUES (13, 'DESERT_S', '02/05/2023', 75.00);
INSERT INTO bookings VALUES (14, 'DESERT_S', '02/06/2023', 34.00);
INSERT INTO bookings VALUES (15, 'DESERT_S', '02/09/2023', 85.00);

INSERT INTO bookings VALUES (16, 'DESERT_S', '02/12/2023', 23.00);
INSERT INTO bookings VALUES (17, 'DESERT_S', '02/13/2023', 76.00);
INSERT INTO bookings VALUES (18, 'DESERT_S', '02/14/2023', 85.00);

INSERT INTO bookings VALUES (19, 'OCEAN_WV', '02/01/2023', 98.00);
INSERT INTO bookings VALUES (20, 'OCEAN_WV', '02/02/2023', 75.00);
INSERT INTO bookings VALUES (21, 'OCEAN_WV', '02/04/2023', 85.00);

INSERT INTO bookings VALUES (22, 'OCEAN_WV', '02/06/2023', 75.00);
INSERT INTO bookings VALUES (23, 'OCEAN_WV', '02/09/2023', 34.00);
INSERT INTO bookings VALUES (24, 'OCEAN_WV', '02/12/2023', 85.00);

INSERT INTO bookings VALUES (25, 'OCEAN_WV', '02/13/2023', 23.00);
INSERT INTO bookings VALUES (26, 'OCEAN_WV', '02/14/2023', 76.00);
INSERT INTO bookings VALUES (27, 'OCEAN_WV', '02/16/2023', 85.00);

INSERT INTO bookings VALUES (28, 'CITY_BLD', '02/01/2023', 98.00);
INSERT INTO bookings VALUES (29, 'CITY_BLD', '02/02/2023', 75.00);
INSERT INTO bookings VALUES (30, 'CITY_BLD', '02/04/2023', 85.00);

INSERT INTO bookings VALUES (31, 'CITY_BLD', '02/12/2023', 75.00);
INSERT INTO bookings VALUES (32, 'CITY_BLD', '02/13/2023', 34.00);
INSERT INTO bookings VALUES (33, 'CITY_BLD', '02/17/2023', 85.00);

INSERT INTO bookings VALUES (34, 'CITY_BLD', '02/22/2023', 23.00);
INSERT INTO bookings VALUES (35, 'CITY_BLD', '02/23/2023', 76.00);
INSERT INTO bookings VALUES (36, 'CITY_BLD', '02/24/2023', 85.00);
```

 En este ejemplo de consulta, los registros de reserva se suman para obtener un total de cada semana. La fecha de finalización de cada semana se convierte en un nombre de columna.

```
SELECT * FROM
    (SELECT
       booking_id,
       (date_trunc('week', booking_date::date) + '5 days'::interval)::date as enddate,
       hotel_code AS "hotel code"
FROM bookings
) PIVOT (
    count(booking_id) FOR enddate IN ('2023-02-04','2023-02-11','2023-02-18') 
);
```

La consulta genera el siguiente resultado.

```
 hotel code | 2023-02-04  | 2023-02-11 | 2023-02-18
------------+-------------+------------+----------
 FOREST_L   |           3 |          2 |        1
 DESERT_S   |           4 |          3 |        2
 OCEAN_WV   |           3 |          3 |        3
 CITY_BLD   |           3 |          1 |        2
```

 Amazon Redshift no admite CROSSTAB para dinamizar en varias columnas. Pero puede cambiar los datos de filas a columnas, de forma similar a una agregación con PIVOT, con una consulta como la siguiente. Para ello se utilizan los mismos datos de muestra de reservas que en el ejemplo anterior.

```
SELECT 
  booking_date,
  MAX(CASE WHEN hotel_code = 'FOREST_L' THEN 'forest is booked' ELSE '' END) AS FOREST_L,
  MAX(CASE WHEN hotel_code = 'DESERT_S' THEN 'desert is booked' ELSE '' END) AS DESERT_S,
  MAX(CASE WHEN hotel_code = 'OCEAN_WV' THEN 'ocean is booked' ELSE '' END)  AS OCEAN_WV
FROM bookings
GROUP BY booking_date
ORDER BY booking_date asc;
```

La consulta de ejemplo da como resultado las fechas de reserva que aparecen junto a frases cortas que indican qué hoteles están reservados.

```
 booking_date  | forest_l         | desert_s         | ocean_wv
---------------+------------------+------------------+--------------------
 2023-02-01    | forest is booked | desert is booked |  ocean is booked
 2023-02-02    | forest is booked | desert is booked |  ocean is booked
 2023-02-04    | forest is booked | desert is booked |  ocean is booked
 2023-02-05    |                  | desert is booked |        
 2023-02-06    |                  | desert is booked |
```

Las siguientes notas de uso se indican a continuación para `PIVOT`:
+ `PIVOT` se puede aplicar a tablas, subconsultas y expresiones de tabla comunes (CTE). `PIVOT` no se puede aplicar a ninguna expresión `JOIN`, CTE recursivos, expresiones `PIVOT` o `UNPIVOT`. Tampoco se admiten expresiones `SUPER` sin anidar ni tablas anidadas Redshift Spectrum.
+  `PIVOT` admite las funciones de agregación `COUNT`, `SUM`, `MIN`, `MAX` y `AVG`. 
+ La expresión de agregación `PIVOT` tiene que ser una llamada de una función de agregación admitida. No se admiten expresiones complejas además de las de agregación. Los argumentos de agregación no pueden contener referencias a tablas distintas de las tablas `PIVOT` de entrada. Tampoco se admiten las referencias correlacionadas a una consulta principal. El argumento agregado puede contener subconsultas. Se pueden correlacionar internamente o en la tabla de entrada `PIVOT`.
+  Los valores de la lista `PIVOT IN` no pueden ser referencias de columna ni subconsultas. Cada valor debe ser compatible con el tipo de referencia de columna `FOR`. 
+  Si los valores de la lista `IN` no tienen alias, `PIVOT` genera nombres de columna predeterminados. Para valores `IN` constantes como “abc” o 5, el nombre de columna predeterminado es la constante en sí. Para cualquier expresión compleja, el nombre de la columna es un nombre predeterminado estándar de Amazon Redshift, como `?column?`. 

## Ejemplos de UNPIVOT
<a name="r_FROM_clause-unpivot-examples"></a>

Configure los datos de muestra y utilícelos para ejecutar los ejemplos posteriores.

```
CREATE TABLE count_by_color (quality varchar, red int, green int, blue int);

INSERT INTO count_by_color VALUES ('high', 15, 20, 7);
INSERT INTO count_by_color VALUES ('normal', 35, NULL, 40);
INSERT INTO count_by_color VALUES ('low', 10, 23, NULL);
```

`UNPIVOT` en las columnas de entrada roja, verde y azul.

```
SELECT *
FROM (SELECT red, green, blue FROM count_by_color) UNPIVOT (
    cnt FOR color IN (red, green, blue)
);
```

La consulta genera el siguiente resultado.

```
 color | cnt
-------+-----
 red   |  15
 red   |  35
 red   |  10
 green |  20
 green |  23
 blue  |   7
 blue  |  40
```

De manera predeterminada, los valores `NULL` de la columna de entrada se omiten y no producen una fila de resultados. 

En el siguiente ejemplo, se muestra `UNPIVOT` con `INCLUDE NULLS`.

```
SELECT *
FROM (
    SELECT red, green, blue
    FROM count_by_color
) UNPIVOT INCLUDE NULLS (
    cnt FOR color IN (red, green, blue)
);
```

Se genera el siguiente resultado.

```
 color | cnt
-------+-----
 red   |  15
 red   |  35
 red   |  10
 green |  20
 green |
 green |  23
 blue  |   7
 blue  |  40
 blue  |
```

Si se configura el parámetro `INCLUDING NULLS`, los valores de entrada `NULL` generan filas de resultados.

Un ejemplo de `The following query shows UNPIVOT` con `quality` como columna implícita.

```
SELECT *
FROM count_by_color UNPIVOT (
    cnt FOR color IN (red, green, blue)
);
```

La consulta genera el siguiente resultado.

```
 quality | color | cnt
---------+-------+-----
 high    | red   |  15
 normal  | red   |  35
 low     | red   |  10
 high    | green |  20
 low     | green |  23
 high    | blue  |   7
 normal  | blue  |  40
```

Columnas de tabla de entrada a las que no se hace referencia en la definición de `UNPIVOT`, se agregan implícitamente a la tabla de resultados. Este es el caso de la columna `quality` del ejemplo.

En el siguiente ejemplo, se muestra `UNPIVOT` con alias para valores en la lista `IN`.

```
SELECT *
FROM count_by_color UNPIVOT (
    cnt FOR color IN (red AS r, green AS g, blue AS b)
);
```

La consulta anterior genera el siguiente resultado.

```
 quality | color | cnt
---------+-------+-----
 high    | r     |  15
 normal  | r     |  35
 low     | r     |  10
 high    | g     |  20
 low     | g     |  23
 high    | b     |   7
 normal  | b     |  40
```

El operador `UNPIVOT` acepta alias opcionales en cada valor de la lista `IN`. Cada alias proporciona personalización de los datos de cada columna `value`.

Las siguientes notas de uso se indican a continuación para `UNPIVOT`.
+ `UNPIVOT` se puede aplicar a tablas, subconsultas y expresiones de tabla comunes (CTE). `UNPIVOT` no se puede aplicar a ninguna expresión `JOIN`, CTE recursivos, expresiones `PIVOT` o `UNPIVOT`. Tampoco se admiten expresiones `SUPER` sin anidar ni tablas anidadas Redshift Spectrum.
+ La lista `UNPIVOT IN` debe contener solo referencias de columna de tabla de entrada. Las columnas de la lista `IN` deben tener un tipo común con el que todas sean compatibles. La columna de valor `UNPIVOT` tiene este tipo común. La columna de nombre `UNPIVOT` es de tipo `VARCHAR`.
+ Si un valor de la lista `IN` no tiene un alias, `UNPIVOT` utiliza el nombre de la columna como valor predeterminado.

# Ejemplos de JOIN
<a name="r_Join_examples"></a>

Se utiliza una cláusula JOIN de SQL para combinar los datos de dos o más tablas en función de los campos comunes. Es posible que los resultados cambien o no cambien según el método de combinación especificado. Para obtener más información acerca de la sintaxis de la cláusula JOIN, consulte [Parameters](r_FROM_clause30.md#r_FROM_clause30-parameters). 

En los siguientes ejemplos se usan datos de los ejemplos de `TICKIT`. Para obtener más información acerca del esquema de base de datos, consulte [Base de datos de muestra](c_sampledb.md). Para obtener información sobre cómo cargar datos de ejemplo, consulte [Carga de datos](https://docs.aws.amazon.com/redshift/latest/gsg/rs-gsg-create-sample-db.html) en la *Guía de introducción a Amazon Redshift*.

La siguiente consulta es una combinación interna (sin la palabra clave JOIN) entre la tabla LISTING y la tabla SALES, donde LISTID de la tabla LISTING está entre 1 y 5. Esta consulta relaciona los valores de la columna LISTID en la tabla LISTING (la tabla izquierda) y la tabla SALES (la tabla derecha). Los resultados muestran que LISTID 1, 4 y 5 coinciden con los criterios.

```
select listing.listid, sum(pricepaid) as price, sum(commission) as comm
from listing, sales
where listing.listid = sales.listid
and listing.listid between 1 and 5
group by 1
order by 1;

listid | price  |  comm
-------+--------+--------
     1 | 728.00 | 109.20
     4 |  76.00 |  11.40
     5 | 525.00 |  78.75
```

La siguiente consulta es una combinación externa izquierda. Las combinaciones externas izquierdas y derechas conservan valores de una de las tablas combinadas cuando no se encuentra una coincidencia en la otra tabla. Las tablas izquierda y derecha son la primera tabla y la segunda tabla que aparecen en la sintaxis. Los valores NULL se utilizan para rellenar los "espacios" en el conjunto de resultados. Esta consulta relaciona los valores de la columna LISTID en la tabla LISTING (la tabla izquierda) y la tabla SALES (la tabla derecha). Los resultados muestran que LISTID 2 y 3 no tienen ventas.

```
select listing.listid, sum(pricepaid) as price, sum(commission) as comm
from listing left outer join sales on sales.listid = listing.listid
where listing.listid between 1 and 5
group by 1
order by 1;

listid | price  |  comm
-------+--------+--------
     1 | 728.00 | 109.20
     2 | NULL   | NULL
     3 | NULL   | NULL
     4 |  76.00 |  11.40
     5 | 525.00 |  78.75
```

La siguiente consulta es una combinación externa derecha. Esta consulta relaciona los valores de la columna LISTID en la tabla LISTING (la tabla izquierda) y la tabla SALES (la tabla derecha). Los resultados muestran que LISTID 1, 4 y 5 coinciden con los criterios.

```
select listing.listid, sum(pricepaid) as price, sum(commission) as comm
from listing right outer join sales on sales.listid = listing.listid
where listing.listid between 1 and 5
group by 1
order by 1;

listid | price  |  comm
-------+--------+--------
     1 | 728.00 | 109.20
     4 |  76.00 |  11.40
     5 | 525.00 |  78.75
```

La siguiente consulta es una combinación completa. Las combinaciones completas retienen valores de las tablas combinadas cuando no se encuentra una coincidencia en la otra tabla. Las tablas izquierda y derecha son la primera tabla y la segunda tabla que aparecen en la sintaxis. Los valores NULL se utilizan para rellenar los "espacios" en el conjunto de resultados. Esta consulta relaciona los valores de la columna LISTID en la tabla LISTING (la tabla izquierda) y la tabla SALES (la tabla derecha). Los resultados muestran que LISTID 2 y 3 no tienen ventas.

```
select listing.listid, sum(pricepaid) as price, sum(commission) as comm
from listing full join sales on sales.listid = listing.listid
where listing.listid between 1 and 5
group by 1
order by 1;

listid | price  |  comm
-------+--------+--------
     1 | 728.00 | 109.20
     2 | NULL   | NULL
     3 | NULL   | NULL
     4 |  76.00 |  11.40
     5 | 525.00 |  78.75
```

La siguiente consulta es una combinación completa. Esta consulta relaciona los valores de la columna LISTID en la tabla LISTING (la tabla izquierda) y la tabla SALES (la tabla derecha). Solo se encuentran en los resultados filas que no dan lugar a ninguna venta (LISTID 2 y 3).

```
select listing.listid, sum(pricepaid) as price, sum(commission) as comm
from listing full join sales on sales.listid = listing.listid
where listing.listid between 1 and 5
and (listing.listid IS NULL or sales.listid IS NULL)
group by 1
order by 1;

listid | price  |  comm
-------+--------+--------
     2 | NULL   | NULL
     3 | NULL   | NULL
```

El siguiente ejemplo es una combinación interna con la cláusula ON. En este caso, las filas NULL no se devuelven.

```
select listing.listid, sum(pricepaid) as price, sum(commission) as comm
from sales join listing
on sales.listid=listing.listid and sales.eventid=listing.eventid
where listing.listid between 1 and 5
group by 1
order by 1;

listid | price  |  comm
-------+--------+--------
     1 | 728.00 | 109.20
     4 |  76.00 |  11.40
     5 | 525.00 |  78.75
```

La siguiente consulta es una combinación cruzada o cartesiana de la tabla LISTING y la tabla SALES con un predicado para limitar los resultados. Esta consulta coincide con los valores de columna LISTID de la tabla SALES y la tabla LISTING para LISTID 1, 2, 3, 4 y 5 de ambas tablas. Los resultados muestran que 20 filas coinciden con los criterios.

```
select sales.listid as sales_listid, listing.listid as listing_listid
from sales cross join listing
where sales.listid between 1 and 5
and listing.listid between 1 and 5
order by 1,2;

sales_listid | listing_listid
-------------+---------------
1            | 1
1            | 2
1            | 3
1            | 4
1            | 5
4            | 1
4            | 2
4            | 3
4            | 4
4            | 5
5            | 1
5            | 1
5            | 2
5            | 2
5            | 3
5            | 3
5            | 4
5            | 4
5            | 5
5            | 5
```

El ejemplo siguiente es una combinación natural entre dos tablas. En este caso, las columnas listid, sellerid, eventid y dateid tienen nombres y tipos de datos idénticos en ambas tablas y, por lo tanto, se utilizan como columnas de combinación. Los resultados tienen un límite de cinco filas.

```
select listid, sellerid, eventid, dateid, numtickets
from listing natural join sales
order by 1
limit 5;

listid | sellerid  | eventid | dateid | numtickets
-------+-----------+---------+--------+-----------
113    | 29704     | 4699    | 2075   | 22
115    | 39115     | 3513    | 2062   | 14
116    | 43314     | 8675    | 1910   | 28
118    | 6079      | 1611    | 1862   | 9
163    | 24880     | 8253    | 1888   | 14
```

El ejemplo siguiente es una combinación entre dos tablas con la cláusula USING. En este caso, las columnas listid y eventid se utilizan como columnas de combinación. Los resultados tienen un límite de cinco filas.

```
select listid, listing.sellerid, eventid, listing.dateid, numtickets
from listing join sales
using (listid, eventid)
order by 1
limit 5;

listid | sellerid | eventid | dateid | numtickets
-------+----------+---------+--------+-----------
1      | 36861    | 7872    | 1850   | 10
4      | 8117     | 4337    | 1970   | 8
5      | 1616     | 8647    | 1963   | 4
5      | 1616     | 8647    | 1963   | 4
6      | 47402    | 8240    | 2053   | 18
```

La siguiente consulta es una combinación interna de dos subconsultas en la cláusula FROM. La consulta busca la cantidad de tickets vendidos y sin vender para diferentes categorías de eventos (conciertos y espectáculos). Estas subconsultas de la cláusula FROM son subconsultas de *tabla*; pueden devolver varias columnas y filas.

```
select catgroup1, sold, unsold
from
(select catgroup, sum(qtysold) as sold
from category c, event e, sales s
where c.catid = e.catid and e.eventid = s.eventid
group by catgroup) as a(catgroup1, sold)
join
(select catgroup, sum(numtickets)-sum(qtysold) as unsold
from category c, event e, sales s, listing l
where c.catid = e.catid and e.eventid = s.eventid
and s.listid = l.listid
group by catgroup) as b(catgroup2, unsold)

on a.catgroup1 = b.catgroup2
order by 1;

catgroup1 |  sold  | unsold
----------+--------+--------
Concerts  | 195444 |1067199
Shows     | 149905 | 817736
```

# Ejemplos de UNNEST
<a name="r_FROM_clause-unnest-examples"></a>

UNNEST es un parámetro de la cláusula FROM que expande los datos anidados en columnas que contienen los elementos no anidados de los datos. Para obtener información sobre cómo anular el anidamiento de los datos, consulte [Consulta de datos semiestructurados](query-super.md).

La siguiente instrucción crea y rellena la tabla `orders`, que contiene una columna `products` con matrices de ID de productos. En los ejemplos de esta sección se utilizan los datos de ejemplo de esta tabla. 

```
CREATE TABLE orders (
    order_id INT,
    products SUPER
);

-- Populate table
INSERT INTO orders VALUES
(1001, JSON_PARSE('[
        {
            "product_id": "P456",
            "name": "Monitor",
            "price": 299.99,
            "quantity": 1,
            "specs": {
                "size": "27 inch",
                "resolution": "4K"
            }
        }
    ]
')),
(1002, JSON_PARSE('
    [
        {
            "product_id": "P567",
            "name": "USB Cable",
            "price": 9.99,
            "quantity": 3
        },
        {
            "product_id": "P678",
            "name": "Headphones",
            "price": 159.99,
            "quantity": 1,
            "specs": {
                "type": "Wireless",
                "battery_life": "20 hours"
            }
        }
    ]
'));
```

A continuación se muestran algunos ejemplos de consultas de anulación de anidamiento con los datos de ejemplo mediante la sintaxis PartiQL.

## Anulación del anidamiento de una matriz sin una columna OFFSET
<a name="r_FROM_clause-unnest-examples-no-offset"></a>

La siguiente consulta anula el anidamiento de las matrices SUPER en la columna products, donde cada fila representa un elemento del pedido en `order_id`.

```
SELECT o.order_id, unnested_products.product
FROM orders o, UNNEST(o.products) AS unnested_products(product);

 order_id |                                                           product                                                           
----------+-----------------------------------------------------------------------------------------------------------------------------
     1001 | {"product_id":"P456","name":"Monitor","price":299.99,"quantity":1,"specs":{"size":"27 inch","resolution":"4K"}}
     1002 | {"product_id":"P567","name":"USB Cable","price":9.99,"quantity":3}
     1002 | {"product_id":"P678","name":"Headphones","price":159.99,"quantity":1,"specs":{"type":"Wireless","battery_life":"20 hours"}}
(3 rows)
```

La siguiente consulta encuentra el producto más caro de cada pedido.

```
SELECT o.order_id, MAX(unnested_products.product)
FROM orders o, UNNEST(o.products) AS unnested_products(product);

 order_id |                                                           product                                                           
----------+-----------------------------------------------------------------------------------------------------------------------------
     1001 | {"product_id":"P456","name":"Monitor","price":299.99,"quantity":1,"specs":{"size":"27 inch","resolution":"4K"}}
     1002 | {"product_id":"P678","name":"Headphones","price":159.99,"quantity":1,"specs":{"type":"Wireless","battery_life":"20 hours"}}
(2 rows)
```

## Anulación del anidamiento de una matriz con una columna OFFSET implícita
<a name="r_FROM_clause-unnest-examples-implicit-offset"></a>

La siguiente consulta utiliza el parámetro `UNNEST ... WITH OFFSET` para mostrar la posición basada en cero de cada producto en la matriz de pedidos.

```
SELECT o.order_id, up.product, up.offset_col
FROM orders o, UNNEST(o.products) WITH OFFSET AS up(product);

 order_id |                                                           product                                                           | offset_col 
----------+-----------------------------------------------------------------------------------------------------------------------------+------------
     1001 | {"product_id":"P456","name":"Monitor","price":299.99,"quantity":1,"specs":{"size":"27 inch","resolution":"4K"}}             |          0
     1002 | {"product_id":"P567","name":"USB Cable","price":9.99,"quantity":3}                                                          |          0
     1002 | {"product_id":"P678","name":"Headphones","price":159.99,"quantity":1,"specs":{"type":"Wireless","battery_life":"20 hours"}} |          1
(3 rows)
```

Dado que la instrucción no especifica un alias para la columna de desplazamiento, Amazon Redshift le asigna el nombre predeterminado `offset_col`.

## Anulación del anidamiento de una matriz con una columna OFFSET explícita
<a name="r_FROM_clause-unnest-examples-explicit-offset"></a>

La siguiente consulta también utiliza el parámetro `UNNEST ... WITH OFFSET` para mostrar los productos en las matrices de pedidos. La diferencia entre esta consulta y la del ejemplo anterior es que designa explícitamente la columna de desplazamiento con el alias `idx`.

```
SELECT o.order_id, up.product, up.idx
FROM orders o, UNNEST(o.products) WITH OFFSET AS up(product, idx);

 order_id |                                                           product                                                           | idx 
----------+-----------------------------------------------------------------------------------------------------------------------------+-----
     1001 | {"product_id":"P456","name":"Monitor","price":299.99,"quantity":1,"specs":{"size":"27 inch","resolution":"4K"}}             |   0
     1002 | {"product_id":"P567","name":"USB Cable","price":9.99,"quantity":3}                                                          |   0
     1002 | {"product_id":"P678","name":"Headphones","price":159.99,"quantity":1,"specs":{"type":"Wireless","battery_life":"20 hours"}} |   1
(3 rows)
```