Unión de selección de SQL: ¿es posible anteponer todas las columnas como 'prefijo.*'?

Resuelto foxdonut asked hace 16 años • 27 respuestas

Me pregunto si esto es posible en SQL. Supongamos que tiene dos tablas A y B, selecciona en la tabla A y se une a la tabla B:

SELECT a.*, b.* FROM TABLE_A a JOIN TABLE_B b USING (some_id);

Si la tabla A tiene las columnas 'a_id', 'name' y 'some_id', y la tabla B tiene 'b_id', 'name' y 'some_id', la consulta devolverá las columnas 'a_id', 'name', 'some_id ', 'b_id', 'nombre', 'algún_id'. ¿Hay alguna forma de anteponer los nombres de las columnas de la tabla B sin enumerar cada columna individualmente? El equivalente a esto:

SELECT a.*, b.b_id as 'b.b_id', b.name as 'b.name', b.some_id as 'b.some_id'
FROM TABLE_A a JOIN TABLE_B b USING (some_id);

Pero, como se mencionó, sin enumerar todas las columnas, algo como:

SELECT a.*, b.* as 'b.*'
FROM TABLE_A a JOIN TABLE_B b USING (some_id);

Básicamente, algo que decir, "prefije 'algo' a cada columna devuelta por b.*". ¿Es esto posible o no tengo suerte?

EDICIONES

Los consejos sobre no usar, SELECT *etc., son consejos válidos pero no relevantes en mi contexto, así que aténgase al problema en cuestión: ¿es posible agregar un prefijo (una constante especificada en la consulta SQL) a todos los nombres de columnas de un mesa en una unión?

Mi objetivo final es poder hacer una SELECT *combinación en dos tablas y poder saber, a partir de los nombres de las columnas que obtengo en mi conjunto de resultados, qué columnas provienen de la tabla A y qué columnas provienen de la tabla B. Nuevamente, no quiero tener que enumerar las columnas individualmente, necesito poder hacer un archivo SELECT *.

foxdonut avatar Dec 01 '08 10:12 foxdonut
Aceptado

Parece que la respuesta a su pregunta es no; sin embargo, un truco que puede utilizar es asignar una columna ficticia para separar cada tabla nueva. Esto funciona especialmente bien si está recorriendo un conjunto de resultados para una lista de columnas en un lenguaje de programación como Python o PHP.

SELECT '' as table1_dummy, table1.*, '' as table2_dummy, table2.*, '' as table3_dummy, table3.* FROM table1
JOIN table2 ON table2.table1id = table1.id
JOIN table3 ON table3.table1id = table1.id

Me doy cuenta de que esto no responde exactamente a tu pregunta, pero si eres programador, esta es una excelente manera de separar tablas con nombres de columnas duplicados.

Wayne Bryan avatar Mar 29 '2012 13:03 Wayne Bryan

Veo dos situaciones posibles aquí. En primer lugar, desea saber si existe un estándar SQL para esto que pueda utilizar en general independientemente de la base de datos. No no hay. En segundo lugar, desea saber con respecto a un producto dbms específico. Entonces necesitas identificarlo. Pero imagino que la respuesta más probable es que obtendrá algo como "a.id, b.id", ya que así es como necesitaría identificar las columnas en su expresión SQL. Y la forma más sencilla de averiguar cuál es el valor predeterminado es simplemente enviar dicha consulta y ver qué obtiene. Si desea especificar qué prefijo va antes del punto, puede utilizar "SELECT * FROM a AS my_alias", por ejemplo.

dkretz avatar Dec 01 '2008 03:12 dkretz

Entiendo totalmente por qué esto es necesario; al menos para mí, es útil durante la creación rápida de prototipos cuando es necesario unir muchas tablas, incluidas muchas uniones internas. Tan pronto como el nombre de una columna es el mismo en un segundo comodín de campo "joinedtable.*", los valores de los campos de la tabla principal se anulan con los valores de la tabla unida. Propenso a errores, frustrante y una violación de DRY al tener que especificar manualmente los campos de la tabla con alias una y otra vez...

Aquí hay una función PHP (Wordpress) para lograr esto mediante la generación de código junto con un ejemplo de cómo usarlo. En el ejemplo, se utiliza para generar rápidamente una consulta personalizada que proporcionará los campos de una publicación de WordPress relacionada a la que se hizo referencia a través de un campo de campos personalizados avanzados .

function prefixed_table_fields_wildcard($table, $alias)
{
    global $wpdb;
    $columns = $wpdb->get_results("SHOW COLUMNS FROM $table", ARRAY_A);

    $field_names = array();
    foreach ($columns as $column)
    {
        $field_names[] = $column["Field"];
    }
    $prefixed = array();
    foreach ($field_names as $field_name)
    {
        $prefixed[] = "`{$alias}`.`{$field_name}` AS `{$alias}.{$field_name}`";
    }

    return implode(", ", $prefixed);
}

function test_prefixed_table_fields_wildcard()
{
    global $wpdb;

    $query = "
    SELECT
        " . prefixed_table_fields_wildcard($wpdb->posts, 'campaigns') . ",
        " . prefixed_table_fields_wildcard($wpdb->posts, 'venues') . "
        FROM $wpdb->posts AS campaigns
    LEFT JOIN $wpdb->postmeta meta1 ON (meta1.meta_key = 'venue' AND campaigns.ID = meta1.post_id)
    LEFT JOIN $wpdb->posts venues ON (venues.post_status = 'publish' AND venues.post_type = 'venue' AND venues.ID = meta1.meta_value)
    WHERE 1
    AND campaigns.post_status = 'publish'
    AND campaigns.post_type = 'campaign'
    LIMIT 1
    ";

    echo "<pre>$query</pre>";

    $posts = $wpdb->get_results($query, OBJECT);

    echo "<pre>";
    print_r($posts);
    echo "</pre>";
}

La salida:

SELECT
    `campaigns`.`ID` AS `campaigns.ID`, `campaigns`.`post_author` AS `campaigns.post_author`, `campaigns`.`post_date` AS `campaigns.post_date`, `campaigns`.`post_date_gmt` AS `campaigns.post_date_gmt`, `campaigns`.`post_content` AS `campaigns.post_content`, `campaigns`.`post_title` AS `campaigns.post_title`, `campaigns`.`post_excerpt` AS `campaigns.post_excerpt`, `campaigns`.`post_status` AS `campaigns.post_status`, `campaigns`.`comment_status` AS `campaigns.comment_status`, `campaigns`.`ping_status` AS `campaigns.ping_status`, `campaigns`.`post_password` AS `campaigns.post_password`, `campaigns`.`post_name` AS `campaigns.post_name`, `campaigns`.`to_ping` AS `campaigns.to_ping`, `campaigns`.`pinged` AS `campaigns.pinged`, `campaigns`.`post_modified` AS `campaigns.post_modified`, `campaigns`.`post_modified_gmt` AS `campaigns.post_modified_gmt`, `campaigns`.`post_content_filtered` AS `campaigns.post_content_filtered`, `campaigns`.`post_parent` AS `campaigns.post_parent`, `campaigns`.`guid` AS `campaigns.guid`, `campaigns`.`menu_order` AS `campaigns.menu_order`, `campaigns`.`post_type` AS `campaigns.post_type`, `campaigns`.`post_mime_type` AS `campaigns.post_mime_type`, `campaigns`.`comment_count` AS `campaigns.comment_count`,
    `venues`.`ID` AS `venues.ID`, `venues`.`post_author` AS `venues.post_author`, `venues`.`post_date` AS `venues.post_date`, `venues`.`post_date_gmt` AS `venues.post_date_gmt`, `venues`.`post_content` AS `venues.post_content`, `venues`.`post_title` AS `venues.post_title`, `venues`.`post_excerpt` AS `venues.post_excerpt`, `venues`.`post_status` AS `venues.post_status`, `venues`.`comment_status` AS `venues.comment_status`, `venues`.`ping_status` AS `venues.ping_status`, `venues`.`post_password` AS `venues.post_password`, `venues`.`post_name` AS `venues.post_name`, `venues`.`to_ping` AS `venues.to_ping`, `venues`.`pinged` AS `venues.pinged`, `venues`.`post_modified` AS `venues.post_modified`, `venues`.`post_modified_gmt` AS `venues.post_modified_gmt`, `venues`.`post_content_filtered` AS `venues.post_content_filtered`, `venues`.`post_parent` AS `venues.post_parent`, `venues`.`guid` AS `venues.guid`, `venues`.`menu_order` AS `venues.menu_order`, `venues`.`post_type` AS `venues.post_type`, `venues`.`post_mime_type` AS `venues.post_mime_type`, `venues`.`comment_count` AS `venues.comment_count`
    FROM wp_posts AS campaigns
LEFT JOIN wp_postmeta meta1 ON (meta1.meta_key = 'venue' AND campaigns.ID = meta1.post_id)
LEFT JOIN wp_posts venues ON (venues.post_status = 'publish' AND venues.post_type = 'venue' AND venues.ID = meta1.meta_value)
WHERE 1
AND campaigns.post_status = 'publish'
AND campaigns.post_type = 'campaign'
LIMIT 1

Array
(
    [0] => stdClass Object
        (
            [campaigns.ID] => 33
            [campaigns.post_author] => 2
            [campaigns.post_date] => 2012-01-16 19:19:10
            [campaigns.post_date_gmt] => 2012-01-16 19:19:10
            [campaigns.post_content] => Lorem ipsum
            [campaigns.post_title] => Lorem ipsum
            [campaigns.post_excerpt] => 
            [campaigns.post_status] => publish
            [campaigns.comment_status] => closed
            [campaigns.ping_status] => closed
            [campaigns.post_password] => 
            [campaigns.post_name] => lorem-ipsum
            [campaigns.to_ping] => 
            [campaigns.pinged] => 
            [campaigns.post_modified] => 2012-01-16 21:01:55
            [campaigns.post_modified_gmt] => 2012-01-16 21:01:55
            [campaigns.post_content_filtered] => 
            [campaigns.post_parent] => 0
            [campaigns.guid] => http://example.com/?p=33
            [campaigns.menu_order] => 0
            [campaigns.post_type] => campaign
            [campaigns.post_mime_type] => 
            [campaigns.comment_count] => 0
            [venues.ID] => 84
            [venues.post_author] => 2
            [venues.post_date] => 2012-01-16 20:12:05
            [venues.post_date_gmt] => 2012-01-16 20:12:05
            [venues.post_content] => Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
            [venues.post_title] => Lorem ipsum venue
            [venues.post_excerpt] => 
            [venues.post_status] => publish
            [venues.comment_status] => closed
            [venues.ping_status] => closed
            [venues.post_password] => 
            [venues.post_name] => lorem-ipsum-venue
            [venues.to_ping] => 
            [venues.pinged] => 
            [venues.post_modified] => 2012-01-16 20:53:37
            [venues.post_modified_gmt] => 2012-01-16 20:53:37
            [venues.post_content_filtered] => 
            [venues.post_parent] => 0
            [venues.guid] => http://example.com/?p=84
            [venues.menu_order] => 0
            [venues.post_type] => venue
            [venues.post_mime_type] => 
            [venues.comment_count] => 0
        )
)
Motin avatar Jan 19 '2012 16:01 Motin

La única base de datos que conozco que hace esto es SQLite, dependiendo de los ajustes que configures con PRAGMA full_column_namesy PRAGMA short_column_names. Ver http://www.sqlite.org/pragma.html

De lo contrario, todo lo que puedo recomendar es buscar columnas en un resultado establecido por posición ordinal en lugar de por nombre de columna, si le resulta demasiado complicado escribir los nombres de las columnas en su consulta.

Este es un buen ejemplo de por qué es una mala práctica usarloSELECT * , porque eventualmente necesitarás escribir todos los nombres de las columnas de todos modos.

Entiendo la necesidad de admitir columnas que puedan cambiar de nombre o posición, pero el uso de comodines lo hace más difícil , no más fácil.

Bill Karwin avatar Dec 01 '2008 03:12 Bill Karwin