SQL select join: is it possible to prefix all columns as 'prefix.*'?

后端 未结 22 1737
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-02 06:20

I\'m wondering if this is possible in SQL. Say you have two tables A and B, and you do a select on table A and join on table B:

SELECT a.*, b.* FROM TABLE_A a         


        
相关标签:
22条回答
  • 2020-12-02 06:34

    It seems the answer to your question is no, however one hack you can use is to assign a dummy column to separate each new table. This works especially well if you're looping through a result set for a list of columns in a scripting language such as Python or 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
    

    I realize this doesn't answer your question exactly, but if you're a coder this is a great way to separate tables with duplicate column names. Hope this helps somebody.

    0 讨论(0)
  • 2020-12-02 06:34

    Developing from this solution, this is how I would approach the problem:

    First create a list of all the AS statements:

    DECLARE @asStatements varchar(8000)
    
    SELECT @asStatements = ISNULL(@asStatements + ', ','') + QUOTENAME(table_name) + '.' + QUOTENAME(column_name) + ' AS ' + '[' + table_name + '.' + column_name + ']'
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME = 'TABLE_A' OR TABLE_NAME = 'TABLE_B'
    ORDER BY ORDINAL_POSITION
    

    Then use it in your query:

    EXEC('SELECT ' + @asStatements + ' FROM TABLE_A a JOIN TABLE_B b USING (some_id)');
    

    However, this might need modifications because something similar is only tested in SQL Server. But this code doesn't exactly work in SQL Server because USING is not supported.

    Please comment if you can test/correct this code for e.g. MySQL.

    0 讨论(0)
  • 2020-12-02 06:35

    I totally understand why this is necessary - at least for me it's handy during rapid prototyping when there are a lot of tables necessary to be joined, including many inner joins. As soon as a column name is the same in a second "joinedtable.*" field wild card, the main table's field values are overriden with the joinedtable values. Error prone, frustrating and a violation of DRY when having to manually specify the table fields with aliases over and over...

    Here is a PHP (Wordpress) function to achieve this through code generation together with an example of how to use it. In the example, it is used to rapidly generate a custom query that will provide the fields of a related wordpress post that was referenced through a advanced custom fields field.

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

    The output:

    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
            )
    )
    
    0 讨论(0)
  • 2020-12-02 06:35

    I solved a similar problem of mine by renaming the fields in the tables involved. Yes, I had the privilege of doing this and understand that everybody may not have it. I added prefix to each field within a table representing the table name. Thus the SQL posted by OP would remain unchanged -

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

    and still give the expected results - ease of identifying which table the output fields belongs to.

    0 讨论(0)
  • 2020-12-02 06:38

    I totally understand your problem about duplicated field names.

    I needed that too until I coded my own function to solve it. If you are using PHP you can use it, or code yours in the language you are using for if you have this following facilities.

    The trick here is that mysql_field_table() returns the table name and mysql_field_name() the field for each row in the result if it's got with mysql_num_fields() so you can mix them in a new array.

    This prefixes all columns ;)

    Regards,

    function mysql_rows_with_columns($query) {
        $result = mysql_query($query);
        if (!$result) return false; // mysql_error() could be used outside
        $fields = mysql_num_fields($result);
        $rows = array();
        while ($row = mysql_fetch_row($result)) { 
            $newRow = array();
            for ($i=0; $i<$fields; $i++) {
                $table = mysql_field_table($result, $i);
                $name = mysql_field_name($result, $i);
                $newRow[$table . "." . $name] = $row[$i];
            }
            $rows[] = $newRow;
        }
        mysql_free_result($result);
        return $rows;
    }
    
    0 讨论(0)
  • 2020-12-02 06:38

    There are two ways I can think of to make this happen in a reusable way. One is to rename all of your columns with a prefix for the table they have come from. I have seen this many times, but I really don't like it. I find that it's redundant, causes a lot of typing, and you can always use aliases when you need to cover the case of a column name having an unclear origin.

    The other way, which I would recommend you do in your situation if you are committed to seeing this through, is to create views for each table that alias the table names. Then you join against those views, rather than the tables. That way, you are free to use * if you wish, free to use the original tables with original column names if you wish, and it also makes writing any subsequent queries easier because you have already done the renaming work in the views.

    Finally, I am not clear why you need to know which table each of the columns came from. Does this matter? Ultimately what matters is the data they contain. Whether UserID came from the User table or the UserQuestion table doesn't really matter. It matters, of course, when you need to update it, but at that point you should already know your schema well enough to determine that.

    0 讨论(0)
提交回复
热议问题