web-dev-qa-db-ja.com

SQL select join:すべての列に「prefix。*」の接頭辞を付けることは可能ですか?

SQLでこれが可能かどうか疑問に思っています。 2つのテーブルAとBがあり、テーブルAで選択を行い、テーブルBで結合するとします。

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

テーブルAに列「a_id」、「name」、および「some_id」があり、テーブルBに「b_id」、「name」、および「some_id」がある場合、クエリは列「a_id」、「name」、「some_id」を返します'、' b_id '、' name '、' some_id '。すべての列を個別にリストせずに、テーブルBの列名にプレフィックスを付ける方法はありますか?これと同等:

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

ただし、前述のように、すべての列をリストせずに、次のようにします。

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

基本的に、「b。*によって返されるすべての列の先頭に「何か」を付ける」ということです。これは可能ですか、それとも運が悪いのですか?

よろしくお願いします!

編集:SELECT *などを使用しないことに関するアドバイスは有効なアドバイスですが、私のコンテキストには関係ありませんので、目の前の問題に固執してください-すべてのプレフィックスにプレフィックス(SQLクエリで指定された定数)を追加することは可能ですか結合内のテーブルの列名?

編集:私の最終的な目標は、結合を持つ2つのテーブルでSELECT *を実行し、結果セットに含まれる列の名前から、どの列が表Aから来たのか、どの列が来たのかを知ることができるようにすることです表Bから。繰り返しますが、列を個別にリストする必要はありません。SELECT*を実行できる必要があります。

186
foxdonut

ここには2つの状況があります。まず、データベースに関係なく一般的に使用できる、このためのSQL標準があるかどうかを知りたいです。いいえ、ありません。次に、特定のdbms製品に関して知りたい。次に、それを識別する必要があります。しかし、最も可能性の高い答えは、 "a.id、b.id"のようなものを取得することだと思います。これは、SQL式で列を識別する必要があるからです。そして、デフォルトが何であるかを知る最も簡単な方法は、そのようなクエリを送信して、何が返されるかを確認することです。ドットの前に付けるプレフィックスを指定する場合は、たとえば「SELECT * FROM a AS my_alias」を使用できます。

34
dkretz

あなたの質問への答えはノーと思われますが、使用できるハックの1つは、ダミーテーブルを割り当てて新しいテーブルをそれぞれ分離することです。これは、Pythonや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

私はこれがあなたの質問に正確に答えていないことを理解していますが、あなたがコーダーなら、これは重複する列名を持つテーブルを分離する素晴らしい方法です。これが誰かを助けることを願っています。

65
Wayne Bryan

なぜこれが必要なのかを完全に理解しています。少なくとも、多くの内部結合を含む、結合する必要のあるテーブルが多数あるラピッドプロトタイピングでは便利です。 2番目の「joinedtable。*」フィールドワイルドカードで列名が同じになるとすぐに、メインテーブルのフィールド値がjointable値で上書きされます。エラーが発生しやすく、イライラし、DRYの違反は、エイリアスを使用してテーブルフィールドを何度も手動で指定する必要がある場合...

コード生成とこれの使用方法の例を使用してこれを実現するPHP(Wordpress)関数を次に示します。この例では、高度なカスタムフィールドフィールドを介して参照された関連wordpress投稿のフィールドを提供するカスタムクエリを迅速に生成するために使用されます。

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

出力:

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

PRAGMA full_column_namesおよびPRAGMA short_column_namesを使用して構成する設定に応じて、これを行う唯一のデータベースはSQLiteです。 http://www.sqlite.org/pragma.html を参照してください

それ以外の場合、クエリで列の名前を入力するのが面倒な場合は、列名ではなく順序位置で結果セットの列をフェッチすることをお勧めします。

これは、 SELECT *を使用するのは悪い習慣です の良い例です。最終的には、とにかくすべての列名を入力する必要があるからです。

名前や位置を変更する可能性のある列をサポートする必要があることは理解していますが、ワイルドカードを使用すると、harderが難しくなります。

11
Bill Karwin

私はOPと同じ船に乗っています-私は参加している3つの異なるテーブルから数十のフィールドを持っていますが、そのうちのいくつかは同じ名前(つまり、id、nameなど)を持っています。各フィールドをリストしたくないので、私の解決策は、名前を共有するフィールドをエイリアスし、一意の名前を持つフィールドにselect *を使用することでした。

例えば ​​:

テーブルa:id、name、field1、field2 ...

テーブルb:id、name、field3、field4 ...

aIDとしてa.id、aNameとしてa.nameを選択します。 *、bIDとしてのb.id、bNameとしてのb.name、b。 * .....

結果にアクセスするとき、これらのフィールドのエイリアス名を使用し、「元の」名前を無視します。

たぶん最良の解決策ではないかもしれませんが、それは私のために動作します.... mysqlを使用しています

6
bdt

異なるデータベース製品では、さまざまな答えが得られます。しかし、あなたがこれを非常に遠くまで運ぶなら、あなたは自分自身を傷つけようとしています。必要な列を選択し、独自のエイリアスを指定して各列のIDを明確にし、結果でそれらを区別できるようにする方がはるかに優れています。

5
dkretz

この質問は実際には非常に役立ちます。ソフトウェアプログラミングのすべての明示的な列をリストする必要があるのは、すべての条件に特に注意を払うことです。

デバッグするとき、または特定のプログラマの抽象的な基盤インフラストラクチャの変更可能な実装の代わりに、日常のオフィスツールとしてDBMSを使用しようとすると、多くのSQLをコーディングする必要があります。このシナリオは、データベース変換、移行、管理など、どこでも見つけることができます。これらのSQLのほとんどは一度だけ実行され、二度と使用されません。すべての列名は時間の無駄です。また、SQLの発明はプログラマが使用するためだけのものではないことを忘れないでください。

通常、列名の前にユーティリティビューを作成します。これはpl/pgsqlの関数です。簡単ではありませんが、他のプロシージャ言語に変換できます。

-- Create alias-view for specific table.

create or replace function mkaview(schema varchar, tab varchar, prefix varchar)
    returns table(orig varchar, alias varchar) as $$
declare
    qtab varchar;
    qview varchar;
    qcol varchar;
    qacol varchar;
    v record;
    sql varchar;
    len int;
begin
    qtab := '"' || schema || '"."' || tab || '"';
    qview := '"' || schema || '"."av' || prefix || tab || '"';
    sql := 'create view ' || qview || ' as select';

    for v in select * from information_schema.columns
            where table_schema = schema and table_name = tab
    loop
        qcol := '"' || v.column_name || '"';
        qacol := '"' || prefix || v.column_name || '"';

        sql := sql || ' ' || qcol || ' as ' || qacol;
        sql := sql || ', ';

        return query select qcol::varchar, qacol::varchar;
    end loop;

    len := length(sql);
    sql := left(sql, len - 2); -- trim the trailing ', '.
    sql := sql || ' from ' || qtab;

    raise info 'Execute SQL: %', sql;
    execute sql;
end
$$ language plpgsql;

例:

-- This will create a view "avp_person" with "p_" prefix to all column names.
select * from mkaview('public', 'person', 'p_');

select * from avp_person;
4
Xiè Jìléi

フィールド名の重複に関するあなたの問題を完全に理解しています。

それを解決するために独自の関数をコーディングするまで、それも必要でした。 PHPを使用している場合、それを使用できます。または、次の機能がある場合は、使用している言語でコーディングできます。

ここでのトリックは、mysql_field_table()がテーブル名を返し、mysql_field_name()mysql_num_fields()で取得されている場合、結果の各行のフィールドを返すため、それらを新しい配列に混在させることができます。

これは、すべての列にプレフィックスを付けます;)

よろしく、

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;
}
3
axelbrz

このためのSQL標準はありません。

ただし、コード生成(テーブルの作成または変更時のオンデマンドまたは実行時)を使用すると、これを非常に簡単に行うことができます。

CREATE TABLE [dbo].[stackoverflow_329931_a](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [col2] [nchar](10) NULL,
    [col3] [nchar](10) NULL,
    [col4] [nchar](10) NULL,
 CONSTRAINT [PK_stackoverflow_329931_a] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[stackoverflow_329931_b](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [col2] [nchar](10) NULL,
    [col3] [nchar](10) NULL,
    [col4] [nchar](10) NULL,
 CONSTRAINT [PK_stackoverflow_329931_b] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

DECLARE @table1_name AS varchar(255)
DECLARE @table1_prefix AS varchar(255)
DECLARE @table2_name AS varchar(255)
DECLARE @table2_prefix AS varchar(255)
DECLARE @join_condition AS varchar(255)
SET @table1_name = 'stackoverflow_329931_a'
SET @table1_prefix = 'a_'
SET @table2_name = 'stackoverflow_329931_b'
SET @table2_prefix = 'b_'
SET @join_condition = 'a.[id] = b.[id]'

DECLARE @CRLF AS varchar(2)
SET @CRLF = CHAR(13) + CHAR(10)

DECLARE @a_columnlist AS varchar(MAX)
DECLARE @b_columnlist AS varchar(MAX)
DECLARE @sql AS varchar(MAX)

SELECT @a_columnlist = COALESCE(@a_columnlist + @CRLF + ',', '') + 'a.[' + COLUMN_NAME + '] AS [' + @table1_prefix + COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table1_name
ORDER BY ORDINAL_POSITION

SELECT @b_columnlist = COALESCE(@b_columnlist + @CRLF + ',', '') + 'b.[' + COLUMN_NAME + '] AS [' + @table2_prefix + COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table2_name
ORDER BY ORDINAL_POSITION

SET @sql = 'SELECT ' + @a_columnlist + '
,' + @b_columnlist + '
FROM [' + @table1_name + '] AS a
INNER JOIN [' + @table2_name + '] AS b
ON (' + @join_condition + ')'

PRINT @sql
-- EXEC (@sql)
2
Cade Roux

エイリアスを使用せずにこれを行うことはできません。単に、結合する2つまたは3つのテーブルにそのフィールドが存在する場合、where句でフィールドをどのように参照するのでしょうか。 mysqlの場合、どの1つを参照しようとしているかは不明です。

1
kobejr

これを再利用可能な方法で実現するには、2つの方法が考えられます。 1つは、すべての列の名前を、元のテーブルのプレフィックスで変更することです。私はこれを何度も見ましたが、私は本当にそれが好きではありません。私はそれが冗長であり、多くの入力を引き起こすことを発見し、不明なOriginを持つ列名のケースをカバーする必要があるときはいつでもエイリアスを使用できます。

他の方法は、これを見ることに専念している場合にあなたの状況で行うことをお勧めしますが、テーブル名をエイリアスする各テーブルのビューを作成することです。次に、テーブルではなく、これらのビューに対して結合します。そのように、必要に応じて*を自由に使用でき、必要に応じて元のテーブルを元の列名で自由に使用できます。また、ビューで名前の変更作業を既に行っているため、後続のクエリを簡単に作成できます。

最後に、各列がどのテーブルから来たのかを知る必要がある理由はわかりません。これは問題ですか?最終的に重要なのは、含まれるデータです。 UserIDがUserテーブルから取得されたか、UserQuestionテーブルから取得されたかは、実際には関係ありません。もちろん、それを更新する必要がある場合は重要ですが、その時点で、スキーマを十分に把握してそれを判断する必要があります。

1
RedFilter

または、Red Gate SQL RefactorまたはSQLプロンプトを使用できます。これは、TabボタンをクリックしてSELECT *を列リストに展開します

あなたの場合、SELECT * FROM A JOIN Bと入力すると... *の最後に移動します。 SELECT A.column1、A.column2、....、B.column1、B.column2 FROM A JOIN Bが表示されます

しかし無料ではありません

1
jerryhung

関係するテーブルのフィールドの名前を変更することで、同様の問題を解決しました。はい、私はこれを行う特権を持っていて、誰もがそれを持っていないかもしれないことを理解しています。テーブル名を表すテーブル内の各フィールドにプレフィックスを追加しました。したがって、OPによってポストされたSQLは変更されないままになります-

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

期待どおりの結果が得られます-出力フィールドがどのテーブルに属しているかを簡単に識別できます。

1
Sam

MySQL C-APIを使用している人には、質問に対する直接の回答があります。

SQLが与えられた場合:

  SELECT a.*, b.*, c.* FROM table_a a JOIN table_b b USING (x) JOIN table_c c USING (y)

'mysql_stmt_result_metadata()'の結果は、準備されたSQLクエリからMYSQL_FIELD []構造体へのフィールドの定義を提供します。各フィールドには次のデータが含まれます。

  char *name;                 /* Name of column (may be the alias) */
  char *org_name;             /* Original column name, if an alias */
  char *table;                /* Table of column if column was a field */
  char *org_table;            /* Org table name, if table was an alias */
  char *db;                   /* Database for table */
  char *catalog;              /* Catalog for table */
  char *def;                  /* Default value (set by mysql_list_fields) */
  unsigned long length;       /* Width of column (create length) */
  unsigned long max_length;   /* Max width for selected set */
  unsigned int name_length;
  unsigned int org_name_length;
  unsigned int table_length;
  unsigned int org_table_length;
  unsigned int db_length;
  unsigned int catalog_length;
  unsigned int def_length;
  unsigned int flags;         /* Div flags */
  unsigned int decimals;      /* Number of decimals in field */
  unsigned int charsetnr;     /* Character set */
  enum enum_field_types type; /* Type of field. See mysql_com.h for types */

次のフィールドに注意してください:catalog、table、org_name

これで、SQLのどのフィールドがどのスキーマ(カタログ)およびテーブルに属しているかがわかりました。これは、複数テーブルのSQLクエリから各フィールドを総称的に識別するのに十分であり、何もエイリアスする必要はありません。

実際の製品SqlYOGは、PKフィールドが存在する場合、マルチテーブル結合の各テーブルを個別に更新できるような方法で、この正確なデータを使用することを示しています。

0
J Jorgenson

最近、NodeJSとPostgresでこの問題に遭遇しました。

ES6アプローチ

私が知っているこの機能を提供するRDBMS機能はないので、すべてのフィールドを含むオブジェクトを作成しました、例えば:

const schema = { columns: ['id','another_column','yet_another_column'] }

テーブル名と文字列を連結するためのレデューサーを定義しました:

const prefix = (table, columns) => columns.reduce((previous, column) => {
  previous.Push(table + '.' + column + ' AS ' + table + '_' + column);
  return previous;
}, []);

これは文字列の配列を返します。テーブルごとに呼び出して、結果を結合します。

const columns_joined = [...prefix('tab1',schema.columns), ...prefix('tab2',schema.columns)];

最終的なSQLステートメントを出力します。

console.log('SELECT ' + columns_joined.join(',') + ' FROM tab1, tab2 WHERE tab1.id = tab2.id');
0
Blair

このソリューション から開発すると、これが私が問題に取り組む方法です:

最初に、すべてのASステートメントのリストを作成します。

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

次に、クエリで使用します。

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

ただし、これに似たものはSQL Serverでのみテストされるため、変更が必要になる場合があります。ただし、USINGはサポートされていないため、このコードはSQL Serverで正確に機能しません。

このコードをテスト/修正できる場合はコメントしてくださいMySQL

0
Antonio

ノードに ダミー列またはセンチネル列の使用を示唆する答え に基づいたソリューションを実装しました。次のようなSQLを生成して使用します。

select 
    s.*
  , '' as _prefix__creator_
  , u.*
  , '' as _prefix__speaker_
  , p.*
from statements s 
  left join users u on s.creator_user_id = u.user_id
  left join persons p on s.speaker_person_id = p.person_id

そして、addPrefixes(row)のように、データベースドライバーから取得した行を後処理します。

実装(私のドライバーから返されたfields/rowsに基づいていますが、他のDBドライバーの場合は簡単に変更できるはずです):

const PREFIX_INDICATOR = '_prefix__'
const STOP_PREFIX_INDICATOR = '_stop_prefix'

/** Adds a <prefix> to all properties that follow a property with the name: PREFIX_INDICATOR<prefix> */
function addPrefixes(fields, row) {
  let prefix = null
  for (const field of fields) {
    const key = field.name
    if (key.startsWith(PREFIX_INDICATOR)) {
      if (row[key] !== '') {
        throw new Error(`PREFIX_INDICATOR ${PREFIX_INDICATOR} must not appear with a value, but had value: ${row[key]}`)
      }
      prefix = key.substr(PREFIX_INDICATOR.length)
      delete row[key]
    } else if (key === STOP_PREFIX_INDICATOR) {
      if (row[key] !== '') {
        throw new Error(`STOP_PREFIX_INDICATOR ${STOP_PREFIX_INDICATOR} must not appear with a value, but had value: ${row[key]}`)
      }
      prefix = null
      delete row[key]
    } else if (prefix) {
      const prefixedKey = prefix + key
      row[prefixedKey] = row[key]
      delete row[key]
    }
  }
  return row
}

テスト:

const {
  addPrefixes,
  PREFIX_INDICATOR,
  STOP_PREFIX_INDICATOR,
} = require('./BaseDao')

describe('addPrefixes', () => {
  test('adds prefixes', () => {
    const fields = [
      {name: 'id'},
      {name: PREFIX_INDICATOR + 'my_prefix_'},
      {name: 'foo'},
      {name: STOP_PREFIX_INDICATOR},
      {name: 'baz'},
    ]
    const row = {
      id: 1,
      [PREFIX_INDICATOR + 'my_prefix_']: '',
      foo: 'bar',
      [STOP_PREFIX_INDICATOR]: '',
      baz: 'spaz'
    }
    const expected = {
      id: 1,
      my_prefix_foo: 'bar',
      baz: 'spaz',
    }
    expect(addPrefixes(fields, row)).toEqual(expected)
  })
})
0
Carl G

私がしているのは、Excelを使用して手順を連結することです。たとえば、最初に*を選択してすべての列を取得し、Excelに貼り付けます。次に、列を囲むために必要なコードを書きます。列の前に広告を出す必要があるとしましょう。私はフィールドをa列に、「as prev_」を列Bに、フィールドを再び列cに入れます。列dには列があります。

次に、列eでconcatanateを使用し、それらを一緒にマージして、スペースを必ず含めます。次に、これをSQLコードにカットアンドペーストします。また、このメソッドを使用して、同じフィールドおよび他のより長いコードのcaseステートメントを作成しました。

0
Nathan Michael

新しい列が追加されたり、テーブルの列の順序が非常に頻繁に変更される傾向があるため、通常、select *は悪いコードになります。したがって、列をリストするのが適切なソリューションです。

クエリの実行方法については、mysqlについてはわかりませんが、sqlserverではsyscolumnsから列名を選択し、select句を動的に構築できます。

0
Kozyarchuk

スキーマの変更が心配な場合は、これが役立つ場合があります。1.関連するすべてのテーブルで「DESCRIBEテーブル」クエリを実行します。 2.返されたフィールド名を使用して、選択したエイリアスをプレフィックスとする列名の文字列を動的に構築します。

0
Chris Jacob