240 votes

SQL select join : est-il possible de préfixer toutes les colonnes comme 'prefix.*' ?

Je me demande si cela est possible en SQL. Disons que vous avez deux tables A et B, et que vous faites une sélection sur la table A et une jointure sur la table B :

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

Si la table A possède les colonnes "a_id", "name" et "some_id", et que la table B possède "b_id", "name" et "some_id", la requête renverra les colonnes "a_id", "name", "some_id", "b_id", "name", "some_id". Existe-t-il un moyen de préfixer les noms des colonnes de la table B sans énumérer chaque colonne individuellement ? L'équivalent de ceci :

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);

Mais, comme mentionné, sans énumérer chaque colonne, donc quelque chose comme :

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

En gros, quelque chose comme "préfixer chaque colonne retournée par b.* avec 'quelque chose'". Est-ce possible ou est-ce que je n'ai pas de chance ?

EDITS

Conseils pour ne pas utiliser SELECT * et ainsi de suite sont des conseils valables mais non pertinents dans mon contexte. Veuillez donc vous en tenir au problème en question : est-il possible d'ajouter un préfixe (une constante spécifiée dans la requête SQL) à tous les noms de colonne d'une table dans une jointure ?

Mon but ultime est d'être capable de faire une SELECT * sur deux tables avec une jointure, et être capable de dire, à partir des noms des colonnes que j'obtiens dans mon ensemble de résultats, quelles colonnes proviennent de la table A et quelles colonnes proviennent de la table B. Encore une fois, je ne veux pas avoir à lister les colonnes individuellement, j'ai besoin de pouvoir faire un SELECT * .

0 votes

Qu'attendez-vous exactement du résultat de votre requête ? Je suis confus

0 votes

GregD : Je veux que tous les noms de colonnes qui sortent de b.* soient préfixés avec une constante que je spécifie. Par exemple, au lieu de 'name' et 'number', je veux spécifier, disons, le préfixe 'special_' et obtenir 'special_name' et 'special_number'. Mais je ne veux pas faire cela pour chaque colonne individuellement.

7 votes

Lorsque je fais un SELECT rapide pour voir les colonnes de plusieurs tables, je fais parfois SELECT 'AAAAA', A.*, 'BBBBB', B.* FROM TableA AS A JOIN TableB AS B ON A.ID = B.ID afin d'avoir au moins un identifiant de table lorsque je parcours les lignes.

95voto

Wayne Bryan Points 101

Il semble que la réponse à votre question soit non, mais une astuce que vous pouvez utiliser consiste à attribuer une colonne fictive pour séparer chaque nouvelle table. Cela fonctionne particulièrement bien si vous parcourez en boucle un ensemble de résultats pour une liste de colonnes dans un langage de script tel que Python ou 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

Je me rends compte que cela ne répond pas exactement à votre question, mais si vous êtes un codeur, c'est un excellent moyen de séparer les tables avec des noms de colonnes en double. J'espère que cela aidera quelqu'un.

3 votes

Cela m'aide. Merci beaucoup de partager

35voto

le dorfier Points 27267

Je vois deux situations possibles ici. Premièrement, vous voulez savoir s'il existe une norme SQL pour cela, que vous pouvez utiliser en général quelle que soit la base de données. Non, il n'y en a pas. Deuxièmement, vous voulez savoir par rapport à un produit dbms spécifique. Alors vous devez l'identifier. Mais j'imagine que la réponse la plus probable est que vous obtiendrez quelque chose comme "a.id, b.id" puisque c'est ainsi que vous devrez identifier les colonnes dans votre expression SQL. Et le moyen le plus simple de savoir ce qu'est la valeur par défaut est de soumettre une telle requête et de voir ce que vous obtenez en retour. Si vous voulez spécifier le préfixe qui précède le point, vous pouvez utiliser "SELECT * FROM a AS my_alias", par exemple.

19 votes

Je ne suis pas sûr que cela réponde à votre question. J'utilise MS SQL Server et l'ajout d'un alias après le nom de la table n'ajoute pas l'alias aux noms des colonnes dans le jeu de résultats.

29voto

Motin Points 1004

Je comprends parfaitement pourquoi cela est nécessaire - en tout cas pour moi, c'est pratique lors du prototypage rapide lorsqu'il y a beaucoup de tables à joindre, y compris de nombreuses jointures internes. Dès qu'un nom de colonne est le même dans un deuxième champ joker "joinedtable.*", les valeurs des champs de la table principale sont remplacées par celles de la joinedtable. C'est une source d'erreurs, de frustration et une violation du DRY lorsque l'on doit spécifier manuellement les champs de la table avec des alias, encore et encore...

Voici une fonction PHP (Wordpress) permettant d'y parvenir par la génération de code, ainsi qu'un exemple d'utilisation. Dans l'exemple, elle est utilisée pour générer rapidement une requête personnalisée qui fournira les champs d'un article Wordpress connexe qui a été référencé par le biais d'une balise champs personnalisés avancés champ.

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>";
}

Le résultat :

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
        )
)

1 votes

Cet article est un peu ancien, mais l'approche fonctionnelle est définitivement élégante et fonctionne bien.

14voto

Bill Karwin Points 204877

La seule base de données que je connais qui fait cela est SQLite, selon les paramètres que vous configurez avec PRAGMA full_column_names y PRAGMA short_column_names . Voir http://www.sqlite.org/pragma.html

Sinon, tout ce que je peux recommander, c'est d'extraire les colonnes d'un ensemble de résultats par position ordinale plutôt que par nom de colonne, si vous avez trop de mal à taper les noms des colonnes dans votre requête.

C'est un bon exemple de la raison pour laquelle c'est une mauvaise pratique d'utiliser SELECT * -- parce que vous aurez éventuellement besoin de taper tous les noms de colonnes de toute façon.

Je comprends la nécessité de prendre en charge les colonnes qui peuvent changer de nom ou de position, mais l'utilisation de caractères génériques rend cette tâche difficile. plus difficile pas plus facile.

2 votes

Notez que les deux full_column_names y short_column_names sont déprécié dans SQLite.

5voto

le dorfier Points 27267

Les différents produits de base de données vous donneront des réponses différentes, mais vous risquez de vous faire mal si vous allez très loin. Il vaut mieux choisir les colonnes que vous voulez, et leur donner vos propres alias afin que l'identité de chaque colonne soit claire comme de l'eau de roche, et que vous puissiez les distinguer dans les résultats.

2 votes

Je comprends, mais mon objectif ici est très générique, donc ne pas être explicite n'est pas un problème. En fait, le fait de devoir être spécifique serait être un problème.

0 votes

Voir la soumission supplémentaire ci-dessous. Peut-on utiliser la notation point, qui est probablement ce que vous obtiendrez par défaut ?

0 votes

C'est important pour la lisibilité. J'espérais pouvoir le faire maintenant parce que j'ai un processus CTE noué. ex. CTE_A -> CTE_B -> CTE_C -> CTE_D -> select/insert Il n'est pas nécessaire de spécifier les colonnes que je veux jusqu'à l'instruction select finale et les performances ne sont pas une considération.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X