SQL select join: Tüm sütunlara 'önek. *' Önek eklemek mümkün mü?


206

Bunun SQL'de mümkün olup olmadığını merak ediyorum. İki A ve B tablonuz olduğunu ve A tablosunda bir seçim yaptığınızı ve B tablosuna katıldığınızı varsayalım:

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

Tablo A'da 'a_id', 'ad' ve 'some_id' sütunları varsa ve B tablosunda 'b_id', 'name' ve 'some_id' varsa, sorgu 'a_id', 'name', 'some_id sütunlarını döndürür ',' b_id ',' ad ',' some_id '. Her sütunu ayrı ayrı listelemeden B tablosunun sütun adlarının önüne ön ek eklemenin bir yolu var mı? Bunun eşdeğeri:

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

Ancak, belirtildiği gibi, her sütunu listelemeden, şöyle bir şey:

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

Temel olarak söyleyecek bir şey, "b. * Tarafından döndürülen her sütuna" bir şey "ile ön ek". Bu mümkün mü yoksa şanssız mıyım?

Yardımınız için şimdiden teşekkürler!

DÜZENLEME: SELECT * kullanmamaya ilişkin öneriler geçerli tavsiyedir, ancak bağlamımla ilgili değildir, bu yüzden lütfen eldeki soruna sadık kalın - tüm öneklere bir önek (SQL sorgusunda belirtilen bir sabit) eklemek mümkün mü bir birleştirmedeki tablonun sütun adları?

DÜZENLEME: nihai hedefim birleştirme ile iki tabloda SELECT * yapabilmek ve sonuç kümemde aldığım sütunların adlarından hangi tabloların A tablosundan geldiğini ve hangi sütunların geldiğini söyleyebilmektir. Yine, sütunları tek tek listelemek istemiyorum, bir SELECT * yapabilmem gerekiyor.


Sorgunuzun sonucunun tam olarak ne olmasını bekliyorsunuz? Kafam karıştı
GregD

GregD: b. * 'Dan çıkan tüm sütun adlarının benim belirttiğim bir sabitle önek olmasını istiyorum. Örneğin, 'ad' ve 'sayı' yerine, 'özel_' önekini belirtmek ve 'özel_adı' ve 'özel_sayısı' almak istiyorum. Ancak bunu her sütun için ayrı ayrı yapmak istemiyorum.
foxdonut

6
Birden çok tablodaki sütunları görmek için hızlı bir SEÇİM yaptığımda, bazen 'AAAAA', A. *, 'BBBBB', B. SEÇİN. satırlar boyunca tarama yaparken en azından bir tablo tanımlayıcısına sahip olun
Kristen

Yanıtlar:


35

Burada iki olası durum görüyorum. İlk olarak, bunun için genel olarak veritabanından bağımsız olarak kullanabileceğiniz bir SQL standardı olup olmadığını bilmek istiyorsunuz. Hayır yok. İkinci olarak, belirli bir dbms ürünü ile ilgili bilmek istersiniz. O zaman onu tanımlamanız gerekir. Ancak en olası cevabın, "a.id, b.id" gibi bir şeyi geri alacağınızı hayal ediyorum, çünkü SQL ifadenizdeki sütunları bu şekilde tanımlamanız gerekir. Ve varsayılanın ne olduğunu bulmanın en kolay yolu, sadece böyle bir sorgu göndermek ve geri döndüğünüzü görmek. Noktadan önce hangi önekin geldiğini belirtmek isterseniz, örneğin "SELECT * FROM a AS my_alias" kullanabilirsiniz.


11
Bunun sorunuza nasıl cevap verdiğinden emin değilim. MS SQL Server kullanıyorum ve tablo adı sonuç kümesindeki sütun adlarına takma ad eklemedikten sonra bir takma ad ekliyorum.
paiego

74

Sorunuzun cevabı hayır gibi görünüyor, ancak kullanabileceğiniz bir kesmek, her yeni tabloyu ayırmak için bir kukla sütun atamaktır. Bu, özellikle Python veya PHP gibi bir komut dosyası dilinde sütun listesi için bir sonuç kümesinde döngü yapıyorsanız iyi çalışır.

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

Bunun sorunuzu tam olarak cevaplamadığını anlıyorum, ancak bir kodlayıcıysanız, bu, yinelenen sütun adlarına sahip tabloları ayırmanın harika bir yoludur. Umarım bu birine yardımcı olur.


24

Bunun neden gerekli olduğunu tamamen anlıyorum - en azından benim için, birçok iç birleşim de dahil olmak üzere birleştirilmesi gereken çok sayıda tablo olduğunda hızlı prototipleme sırasında kullanışlıdır. İkinci bir "birleştirilebilir. *" Alan jokerinde sütun adı aynı olur olmaz, ana tablonun alan değerleri birleştirilebilir değerlerle geçersiz kılınır. Hatalı, sinir bozucu ve takma adları defalarca olan tablo alanlarını manuel olarak belirtmeniz gerektiğinde DRY ihlali ...

İşte bunun nasıl kullanılacağı ile ilgili bir örnek ile birlikte kod üretimi yoluyla bunu başarmak için bir PHP (Wordpress) işlevi. Örnekte, hızlı bir şekilde gelişmiş bir özel alanlar alanından başvurulan ilgili bir wordpress yazısının alanlarını sağlayacak özel bir sorgu oluşturmak için kullanılır .

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

Çıktı:

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

13

Bunu yaptığınızı bildiğim tek veritabanı SQLite, PRAGMA full_column_namesve ile yapılandırdığınız ayarlara bağlı olarak PRAGMA short_column_names. Bkz. Http://www.sqlite.org/pragma.html

Aksi takdirde, önerebileceğim tek şey, sorgunuzdaki sütunların adlarını yazmak için çok fazla sorun varsa, sütun adı yerine sıralı konuma göre bir sonuç kümesindeki sütunları getirmektir.

Bu, neden kullanmanın kötü bir uygulama olduğunaSELECT * iyi bir örnektir - çünkü sonunda tüm sütun adlarını yine de yazmanız gerekecektir.

Adı veya konumu değiştirebilecek sütunları destekleme gereğini anlıyorum, ancak joker karakterler kullanmak bunu zorlaştırıyor , daha kolay değil.


2
Her iki unutmayın full_column_namesve short_column_namesedilir kaldırılmış SQLite'ta.
isana

6

OP ile aynı tekneyim - Katıldığım 3 farklı tablodan düzinelerce alanım var, bazıları aynı ada sahip (yani id, name, vb.). Her alanı listelemek istemiyorum, bu yüzden benim çözümüm, bir adı paylaşan alanları diğer adlara takmak ve benzersiz bir ada sahip olanlar için select * kullanmaktı.

Örneğin :

tablo a: kimlik, ad, alan1, alan2 ...

tablo b: kimlik, ad, alan3, alan4 ...

aID olarak a.id, aName olarak a.name seçin, a. *, b.id bID olarak, b.ad bName olarak, b. * .....

Sonuçlara erişirken bize bu alanlar için takma adlar veriyorum ve "orijinal" adları görmezden geliyorum.

Belki en iyi çözüm değil ama benim için çalışıyor .... mysql kullanıyorum


5

Farklı veritabanı ürünleri size farklı cevaplar verecektir; ama bunu çok ileri taşıyorsanız kendinizi incitmek için kuruyorsunuz. İstediğiniz sütunları seçmekten ve onlara kendi takma adlarınızı vermekten daha iyi olursunuz, böylece her bir sütunun kimliği kristal berraklığındadır ve sonuçlarda bunları birbirinden ayırabilirsiniz.


1
Nokta alınan, ancak buradaki amacım çok genel bir şey, bu yüzden açık olmamak bir sorun değil. Aslında, özgü olmak zorunda olurdu bir sorun.
foxdonut

Aşağıdaki diğer gönderilere bakın. Use dot.notation komutunu kullanabilir, bu muhtemelen varsayılan olarak ne olur?
dkretz

Okunabilirlik açısından önemlidir. Bunu şu anda yapmayı umuyordum çünkü CTE sürecini çok beğenmiştim. ex. CTE_A -> CTE_B -> CTE_C -> CTE_D -> seç / ekle Son seçim ifadesi ve performans dikkate alınmayana kadar istediğim sütunları belirtmeye gerek yok.
ThomasRones

5

Bu soru pratikte çok faydalıdır. Yalnızca, tüm koşullarla başa çıkmaya özellikle dikkat ettiğiniz yazılım programlarındaki her açık sütunu listelemek gerekir.

Hata ayıklarken hayal edin veya DBMS'yi günlük ofis aracı olarak kullanmaya çalışın, belirli programcının soyut temel altyapısının değiştirilebilir bir uygulaması yerine, çok sayıda SQL kodlamalıyız. Senaryo, veritabanı dönüştürme, taşıma, yönetim vb. Gibi her yerde bulunabilir. Bu SQL'lerin çoğu yalnızca bir kez yürütülür ve bir daha asla kullanılmaz, her sütun adının sadece zaman kaybı olduğunu verir. Ve SQL'in buluşunun sadece programcıların kullanımı için olmadığını unutmayın.

Genellikle öneki sütun adları ile bir yardımcı program görünümü oluşturacağım, burada pl / pgsql'deki fonksiyon, kolay değil ama diğer prosedür dillerine dönüştürebilirsiniz.

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

Örnekler:

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

select * from avp_person;

3

Yinelenen alan adları ile ilgili sorununuzu tamamen anlıyorum.

Bunu çözmek için kendi fonksiyonumu kodlayana kadar buna ihtiyacım vardı. PHP kullanıyorsanız, aşağıdaki olanaklara sahipseniz onu kullanabilir veya kullandığınız dilde kodlayabilirsiniz.

Buradaki hile, eğer varsa yeni bir dizide karıştırabilmeniz için sonuçtaki her satır için mysql_field_table()tablo adını ve mysql_field_name()alanını döndürür mysql_num_fields().

Bu, tüm sütunlara ön ek ekler;)

Saygılarımızla,

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

2

Bunun için bir SQL standardı yoktur.

Ancak kod oluşturma ile (tablolar oluşturuldukça veya değiştirildikçe veya çalışma zamanında talep üzerine), bunu oldukça kolay bir şekilde yapabilirsiniz:

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)

bu işe yarar ama soru oldukça aptalca. neden yalnızca bir birleşim veya alt sorgu gerçekleştirmiyoruz? Neden sütun adlarına katılmak ve yine de tablo önekleri istiyorsunuz?
D3vtr0n

Cade: bilgi için teşekkürler, bu ilginç. Ne yazık ki, benim durumumda veritabanı oluşturmak / değiştirmek bir seçenek değildir. Devtron: Sorgudan geri dönen bilgileri bir nesnenin farklı özelliklerine eşlemeye çalışıyorsanız, bu bilgiler çok kullanışlı hale gelir.
foxdonut

1
Bazen farklı tablolardaki sütun adları aynıdır, ancak aynı değerleri içermez. Bu nedenle, görünümlerde veya türetilmiş tablolarda (tüm benzersiz sütun adlarına sahip olması gerekir) ayırt etmek için bunları önekleme ihtiyacı.
Cade Roux

@Frederic, kodunuzun bir yerde yaşaması gerekir - bu sadece kodu oluşturur. Yine, bu geliştirme sırasında bir kez veya çalışma zamanında dinamik olarak yapılabilir.
Cade Roux

1

Bunu yeniden kullanılabilir bir şekilde gerçekleştirmenin iki yolu vardır. Birincisi, tüm sütunlarınızı, geldikleri tablo için bir önekle yeniden adlandırmaktır. Bunu birçok kez gördüm, ama gerçekten sevmiyorum. Gereksiz olduğunu, çok fazla yazılmasına neden olduğunu ve belirsiz bir kökene sahip bir sütun adının durumunu kapsamak istediğinizde her zaman takma adları kullanabilirsiniz.

Bunu görmeye karar verdiyseniz, durumunuzda yapmanızı tavsiye edeceğim diğer bir yol, tablo adlarını taklit eden her tablo için görünümler oluşturmaktır. Sonra tablolardan ziyade bu görüşlere katılmalısınız. Bu şekilde, isterseniz * kullanmakta özgürsünüz, isterseniz orijinal sütun adlarına sahip orijinal tabloları kullanmakta özgürsünüz ve ayrıca görünümlerde yeniden adlandırma işini zaten yapmış olduğunuzdan sonraki sorguları yazmayı da kolaylaştırır.

Son olarak, her bir sütunun hangi tablodan geldiğini neden bilmeniz gerektiğinden emin değilim. Bu önemli mi? Sonuçta önemli olan, içerdikleri verilerdir. UserID'nin User tablosundan mı yoksa UserQuestion tablosundan mı geldiği önemli değildir. Elbette, güncellemeniz gerektiğinde önemlidir, ancak bu noktada şemanızı bunu belirleyecek kadar iyi bilmelisiniz.


"Son olarak, her bir sütunun hangi tablodan geldiğini neden bilmeniz gerektiğinden emin değilim. Bu önemli mi?" <- 11 yıl sonra bir kullanım örneği Go'da yapı taramasıdır.
Lee Benson

1

Veya Sekme düğmesini tıklatarak SELECT * öğenizi sütun listelerine genişleten Red Gate SQL Refactor veya SQL İstemi'ni kullanabilirsiniz.

yani sizin durumunuzda, BEKLENEN B'DEN SEÇ * yazdığınızda ... Sekme düğmesinin sonuna git, voila! B BİRLEŞTİRMEDEN B SEÇİN A.column1, A.column2, ...., B.column1, B.column2

Yine de ücretsiz değil


1

Bunu diğer ad olmadan yapamazsınız, çünkü katıldığınız 2 veya 3 tabloda bu alan varsa, nerede yan tümcesinde bir alana nasıl başvuracağınız için? Hangisine başvurmaya çalıştığınız mysql için belirsiz olacaktır.


1

Benzer bir problemi ilgili tablolardaki alanları yeniden adlandırarak çözdüm. Evet, bunu yapma ayrıcalığım vardı ve herkesin sahip olamayacağını anladım. Tablo adını temsil eden bir tablodaki her alana önek ekledim. Böylece OP tarafından gönderilen SQL değişmeden kalır -

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

ve yine de beklenen sonuçları verir - çıktı alanlarının hangi tabloya ait olduğunu belirleme kolaylığı.


0

select * genellikle kötü kod oluşturur, çünkü yeni sütunlar ekleme eğilimi gösterir veya tablolardaki sütunların sırası oldukça sık değişir, bu da genellikle * seçeneğini çok ince bir şekilde keser. Sütunları listelemek doğru çözümdür.

Sorgunuzu nasıl yapacağınıza gelince, mysql'den emin değilsiniz, ancak sqlserver'da syscolumns'tan sütun adlarını seçebilir ve select deyimini dinamik olarak oluşturabilirsiniz.


Nokta alınan, ama benim bağlamda, genel ve dinamik bir şey ihtiyacım var, bu yüzden aslında benim kod eklenen / yeniden sıralanan / vb yeni sütunlara adapte olacaktır. Sütunları tek tek listelemek istemiyorum.
foxdonut

5
Dinamik olarak bir select deyimi oluşturmak için syscolumns arasından seçim korkunç bir hack ve üretimde bunu tavsiye etmem.
Juliet

0

Şema değişiklikleriyle ilgili endişeleriniz varsa, bu sizin için işe yarayabilir: 1. İlgili tüm tablolarda bir 'DESCRIBE tablosu' sorgusu çalıştırın. 2. Seçtiğiniz takma adın önüne bir dizi sütun adı dinamik olarak oluşturmak için döndürülen alan adlarını kullanın.


0

MySQL C-API'sini kullananlar için sorunuza doğrudan bir cevap var.

SQL verildiğinde:

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

'Mysql_stmt_result_metadata ()' sonuçları, hazırlanan SQL sorgunuzdan MYSQL_FIELD [] yapısına alanlarınızın tanımını verir. Her alan aşağıdaki verileri içerir:

  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 */

Aşağıdaki alanlara dikkat edin: katalog, tablo veya org_name

Artık SQL'inizdeki hangi alanların hangi şemaya (katalog) ve tabloya ait olduğunu biliyorsunuz. Bu, herhangi bir alanı diğer adlara gerek kalmadan çok tablolu bir sql sorgusundan genel olarak tanımlamak için yeterlidir.

Gerçek bir ürün olan SqlYOG, bu tam veriyi, PK alanları mevcut olduğunda, çok masalı bir birleşimin her tablosunu bağımsız olarak güncelleyebilecekleri bir malikanede kullandığını göstermektedir.


0

Bu çözümden geliştirme , soruna şu şekilde yaklaşırım:

İlk önce tüm ASifadelerin bir listesini oluşturun :

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

Ardından sorgunuzda kullanın:

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

Ancak, benzer bir şey yalnızca SQL Server'da test edildiğinden, bunun değiştirilmesi gerekebilir. Ancak, USING desteklenmediği için bu kod SQL Server'da tam olarak çalışmaz.

Bu kodu örneğin MySQL için test edebiliyorsanız / düzeltebiliyorsanız lütfen yorum yapın.


0

Kısa süre önce NodeJS ve Postgres'de bu sorunla karşılaştı.

ES6 yaklaşımı

Bu işlevselliği sağlayan bildiğim herhangi bir RDBMS özelliği yok, bu nedenle tüm alanlarımı içeren bir nesne oluşturdum, örneğin:

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

Dizeleri bir tablo adıyla birleştirmek için bir redüktör tanımladı:

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

Bu bir dizi dizeyi döndürür. Her tablo için arayın ve sonuçları birleştirin:

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

Son SQL deyimini çıktılar:

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

Olmaz! Bu biraz haksız SQL enjeksiyonu ve ifadelerle çalışmaz.
ratijas

0

Düğümde kukla veya nöbetçi sütunlar kullanılmasını öneren yanıta dayalı bir çözüm uyguladım . SQL gibi üreterek kullanabilirsiniz:

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

Ve sonra veritabanı sürücüsünden geri aldığınız satırı sonradan işleyin addPrefixes(row).

Uygulama ( sürücüm tarafından gönderilen fields/ rowsdöndürülen, ancak diğer DB sürücüleri için değiştirilmesi kolay olmalıdır):

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
}

Ölçek:

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

Ne yapmak yordamı birleştirmek için Excel kullanmaktır. Örneğin, önce * seçiyorum ve tüm sütunları alıyorum, bunları Excel'e yapıştırıyorum. Sonra sütunu çevrelemek için gereken kodu yazın. Diyelim ki bir grup sütuna reklam eklemem gerekiyor. Ben bir sütunda alanlarım ve B sütununda "prev_" olarak ve yine c sütununda alanlarım olurdu. Sütun d'de bir sütun olurdu.

Daha sonra e sütununda konkatanat kullanın ve boşlukları eklediğinizden emin olarak birleştirin. Sonra bunu kesip sql kodunuza yapıştırın. Ben de aynı alan ve çok yüzlü alan tablosundaki her alan için yapmanız gereken diğer daha uzun kodlar için durum ifadeleri yapmak için bu yöntemi kullandım.


0

Postgres, ben yerine json nesneleri döndürmek için json işlevlerini kullanın .... sonra, sorgulamadan sonra ben _sonson soneki ile alanları json_decode.

IE:

select row_to_json(tab1.*),tab1_json, row_to_json(tab2.*) tab2_json 
 from tab1
 join tab2 on tab2.t1id=tab1.id

daha sonra PHP (veya başka bir dilde), döndürülen sütunlar arasında döngü ve "_json" soneki varsa json_decode () onları döngü (ayrıca sonek kaldırma. Sonunda, ben içeren tüm "tab1" adlı bir nesne olsun tab1 alanları ve tüm tab2 alanlarını içeren "tab2" adlı başka bir alan.


-1

PHP 7.2 + MySQL / Mariadb

MySQL size aynı ada sahip birden fazla alan gönderecektir. Terminal istemcisinde bile. Ancak ilişkisel bir dizi istiyorsanız, anahtarları kendiniz yapmanız gerekir.

Orijinal için @axelbrz'a teşekkürler. Ben yeni php taşıdım ve biraz temizledim:

function mysqli_rows_with_columns($link, $query) {
    $result = mysqli_query($link, $query);
    if (!$result) {
        return mysqli_error($link);
    }
    $field_count = mysqli_num_fields($result);
    $fields = array();
    for ($i = 0; $i < $field_count; $i++) {
        $field = mysqli_fetch_field_direct($result, $i);
        $fields[] = $field->table . '.' . $field->name; # changed by AS
        #$fields[] = $field->orgtable . '.' . $field->orgname; # actual table/field names
    }
    $rows = array();
    while ($row = mysqli_fetch_row($result)) {
        $new_row = array();
        for ($i = 0; $i < $field_count; $i++) {
            $new_row[$fields[$i]] = $row[$i];
        }
        $rows[] = $new_row;
    }
    mysqli_free_result($result);
    return $rows;
}

$link = mysqli_connect('localhost', 'fixme', 'fixme', 'fixme');
print_r(mysqli_rows_with_columns($link, 'select foo.*, bar.* from foo, bar'));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.