एसक्यूएल सिलेक्ट जॉइन: क्या सभी कॉलमों को 'उपसर्ग। *' के रूप में उपसर्ग करना संभव है?


206

मैं सोच रहा था कि क्या यह SQL में संभव है। कहते हैं कि आपके पास ए और बी दो टेबल हैं, और आप टेबल ए पर चयन करते हैं और टेबल बी पर शामिल होते हैं:

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 '। क्या हर स्तंभ को व्यक्तिगत रूप से सूचीबद्ध किए बिना तालिका बी के स्तंभ नामों को उपसर्ग करने का कोई तरीका है? इस के बराबर:

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

मूल रूप से कुछ कहने के लिए, "उपसर्ग हर कॉलम बी द्वारा वापस लौटा। * 'कुछ' के साथ"। क्या यह संभव है या मैं भाग्य से बाहर हूं?

आपकी सहायता के लिये पहले से ही धन्यवाद!

संपादित करें: सेलेक्ट * का उपयोग न करने की सलाह * और मान्य सलाह है, लेकिन मेरे संदर्भ में प्रासंगिक नहीं है, इसलिए कृपया हाथ में समस्या से चिपके रहें - क्या यह सब में एक उपसर्ग (एसक्यूएल क्वेरी में निर्दिष्ट एक निरंतर) जोड़ना संभव है? किसी तालिका में स्तंभ के नाम?

संपादित करें: मेरा अंतिम लक्ष्य दो तालिकाओं पर एक चयन * को एक साथ करने में सक्षम होना है, और यह बताने में सक्षम होना चाहिए कि मेरे परिणाम सेट में मुझे प्राप्त होने वाले स्तंभों के नामों में से तालिका A के कौन से कॉलम आए थे और कौन से कॉलम आए थे तालिका बी से फिर, मैं स्तंभों को व्यक्तिगत रूप से सूचीबद्ध नहीं करना चाहता, मुझे एक चयन * करने में सक्षम होना चाहिए।


आप वास्तव में अपनी क्वेरी के परिणाम की क्या उम्मीद करते हैं? मैं उलझन में हूँ
ग्रेग

ग्रेग: मैं चाहता हूं कि सभी कॉलम नाम जो बी से निकलते हैं। * मेरे द्वारा निर्दिष्ट कुछ स्थिरांक के साथ उपसर्ग किया जाए। उदाहरण के लिए, 'नाम' और 'संख्या' के बजाय, मैं 'विशेष_' उपसर्ग निर्दिष्ट करना चाहता हूं और 'विशेष_नाम' और 'विशेष_नंबर' प्राप्त करना चाहता हूं। लेकिन मैं व्यक्तिगत रूप से प्रत्येक कॉलम के लिए ऐसा नहीं करना चाहता।
foxdonut

6
जब मैं कई तालिकाओं के स्तंभों को देखने के लिए एक त्वरित चयन करता हूं, तो मैं कुछ समय तक 'AAAAA', A. *, 'BBBBB' का चयन करता हूं, B. * तालिका से एक JOIN तालिकाबी के रूप में B पर A.ID = B.ID के रूप में। पंक्तियों के साथ स्कैन करते समय कम से कम एक टेबल आइडेंटिफ़ायर होता है
क्रिस्टन

संभावित डुप्लिकेट: stackoverflow.com/questions/2595068/…
Andrioid

जवाबों:


35

मैं यहां दो संभावित स्थितियों को देखता हूं। पहले, आप जानना चाहते हैं कि क्या इसके लिए कोई SQL मानक है, जिसे आप डेटाबेस की परवाह किए बिना सामान्य रूप से उपयोग कर सकते हैं। नहीं वहाँ नहीं है। दूसरा, आप एक विशिष्ट dbms उत्पाद के संबंध में जानना चाहते हैं। फिर आपको इसकी पहचान करने की आवश्यकता है। लेकिन मैं सबसे संभावित उत्तर की कल्पना करता हूं कि आपको "a.id, b.id" जैसा कुछ वापस मिल जाएगा, क्योंकि आपको अपनी SQL अभिव्यक्ति में कॉलम की पहचान करने की आवश्यकता होगी। और यह पता लगाने का सबसे आसान तरीका है कि डिफ़ॉल्ट क्या है, बस इस तरह की क्वेरी सबमिट करें और देखें कि आपको क्या मिलता है। यदि आप निर्दिष्ट करना चाहते हैं कि क्या उपसर्ग डॉट से पहले आता है, तो आप उदाहरण के लिए, "SELECT * FROM as AS my_alias" का उपयोग कर सकते हैं।


11
मुझे यकीन नहीं है कि यह आपके सवाल का जवाब कैसे देता है। मैं MS SQL सर्वर का उपयोग कर रहा हूं और तालिका के नाम के बाद एक उपनाम जोड़ रहा हूं जो परिणाम में कॉलम नामों में उपनाम को संलग्न नहीं करता है।
पहिएगो

74

ऐसा लगता है कि आपके प्रश्न का उत्तर नहीं है, हालांकि आप जिस एक हैक का उपयोग कर सकते हैं वह प्रत्येक नई तालिका को अलग करने के लिए एक डमी कॉलम निर्दिष्ट करना है। यह विशेष रूप से अच्छी तरह से काम करता है यदि आप एक स्क्रिप्टिंग भाषा जैसे पाइथन या पीएचपी में कॉलम की सूची के लिए निर्धारित परिणाम के माध्यम से लूप कर रहे हैं।

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

मुझे लगता है कि यह आपके प्रश्न का सटीक उत्तर नहीं देता है, लेकिन यदि आप एक कोडर हैं तो यह डुप्लिकेट कॉलम नामों के साथ तालिकाओं को अलग करने का एक शानदार तरीका है। आशा है कि यह किसी की मदद करता है।


24

मैं पूरी तरह से समझता हूं कि यह क्यों आवश्यक है - कम से कम मेरे लिए यह तेजी से प्रोटोटाइप के दौरान काम करता है जब कई टेबल शामिल होने के लिए आवश्यक हैं, जिसमें कई आंतरिक जोड़ शामिल हैं। जैसे ही एक कॉलम का नाम एक दूसरे "ज्वाइनटेबल। *" फील्ड वाइल्ड कार्ड में समान होता है, मुख्य टेबल के फील्ड वैल्यूज को ज्वाइंटटेबल वैल्यू के साथ ओवरराइड किया जाता है। त्रुटि, निराशा और DRY का उल्लंघन जब मैन्युअल रूप से उपनामों के साथ तालिका क्षेत्रों को निर्दिष्ट करने के लिए ...

इसे उपयोग करने के तरीके के साथ कोड पीढ़ी के माध्यम से इसे प्राप्त करने के लिए एक PHP (वर्डप्रेस) फ़ंक्शन है। उदाहरण में, यह तेजी से एक कस्टम क्वेरी उत्पन्न करने के लिए उपयोग किया जाता है जो संबंधित वर्डप्रेस पोस्ट के फ़ील्ड प्रदान करेगा जिसे एक उन्नत कस्टम फ़ील्ड फ़ील्ड के माध्यम से संदर्भित किया गया था ।

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

13

एकमात्र डेटाबेस जो मुझे पता है कि यह SQLite है, जो आपके द्वारा कॉन्फ़िगर की गई सेटिंग्स पर निर्भर करता है PRAGMA full_column_namesऔर PRAGMA short_column_namesHttp://www.sqlite.org/pragma.html देखें

अन्यथा मैं सभी की सिफारिश कर सकता हूं कि कॉलम नाम के बजाय क्रमिक स्थिति द्वारा निर्धारित परिणाम में कॉलम लाना है, अगर आपके लिए अपनी क्वेरी में कॉलम के नाम टाइप करना बहुत अधिक परेशानी है।

यह एक अच्छा उदाहरण है कि इसका उपयोग करनाSELECT * क्यों बुरा है - क्योंकि आखिरकार आपको सभी कॉलम नामों को वैसे भी टाइप करना होगा।

मैं उन स्तंभों का समर्थन करने की आवश्यकता समझता हूं जो नाम या स्थिति को बदल सकते हैं, लेकिन वाइल्डकार्ड का उपयोग करना कठिन बना देता है , आसान नहीं।


2
ध्यान दें कि दोनों full_column_namesऔर short_column_namesकर रहे हैं पदावनत SQLite में।
इसाना

6

मैं ओपी की तरह एक ही नाव में हूं - मेरे पास 3 अलग-अलग तालिकाओं से दर्जनों फ़ील्ड हैं जो मैं शामिल हो रहा हूं, जिनमें से कुछ का नाम एक ही है (यानी आईडी, नाम, आदि)। मैं प्रत्येक क्षेत्र को सूचीबद्ध नहीं करना चाहता, इसलिए मेरा समाधान उन क्षेत्रों को अन्य नाम देना था जिन्होंने एक नाम साझा किया और उन लोगों के लिए चयन * का उपयोग किया जिनके पास एक अद्वितीय नाम है।

उदाहरण के लिए :

तालिका a: आईडी, नाम, फ़ील्ड 1, फ़ील्ड 2 ...

तालिका b: आईडी, नाम, फ़ील्ड 3, फ़ील्ड 4 ...

a.id के रूप में a.id चुनें, a .नाम के रूप में a.name, a। *, b.id as bID, b.name as bName, b। * .....

परिणामों तक पहुँचते समय हम इन क्षेत्रों के लिए अन्य नाम देते हैं और "मूल" नामों को अनदेखा करते हैं।

शायद सबसे अच्छा समाधान नहीं है, लेकिन यह मेरे लिए काम करता है .... मैं mysql का उपयोग करता हूं


5

डिफरेंट डेटाबेस उत्पाद आपको अलग-अलग उत्तर देंगे; लेकिन यदि आप इसे बहुत दूर ले जाते हैं तो आप खुद को चोट के लिए खड़ा कर रहे हैं आप अपने इच्छित कॉलमों का चयन करना बेहतर समझते हैं, और उन्हें अपने स्वयं के उपनाम देना ताकि प्रत्येक स्तंभ की पहचान क्रिस्टल-स्पष्ट हो, और आप उन्हें परिणामों में अलग बता सकते हैं।


1
पॉइंट लिया गया, लेकिन यहाँ मेरा लक्ष्य कुछ बहुत सामान्य है, इसलिए स्पष्ट नहीं होना कोई समस्या नहीं है। वास्तव में, विशिष्ट होना करने के लिए होगा एक समस्या हो।
foxdonut

नीचे प्रस्तुत आगे देखें। आप डॉट.नोटेशन का उपयोग कर सकते हैं, जो कि संभवत: आपको डिफ़ॉल्ट मिलेगा।
dkretz 3

यह पठनीयता के लिए महत्वपूर्ण है। मैं अभी यह करने की उम्मीद कर रहा था, क्योंकि मेरे पास एक सीटीई सीटीई प्रक्रिया है। पूर्व। CTE_A -> CTE_B -> CTE_C -> CTE_D -> चयन / सम्मिलित करें अंतिम चयन विवरण और प्रदर्शन पर विचार नहीं होने तक मुझे इच्छित कॉलम निर्दिष्ट करने की कोई आवश्यकता नहीं है।
थॉमसरोन

5

यह प्रश्न अभ्यास में बहुत उपयोगी है। सॉफ्टवेयर प्रोग्रामिंग में हर स्पष्ट कॉलम को सूचीबद्ध करना आवश्यक है, जहां आप सभी परिस्थितियों से निपटने के लिए विशेष सावधानी बरतते हैं।

डिबगिंग की कल्पना करें, या, विशिष्ट प्रोग्रामर के अमूर्त अंतर्निहित बुनियादी ढांचे के कुछ परिवर्तनशील कार्यान्वयन के बजाय, दैनिक कार्यालय उपकरण के रूप में डीबीएमएस का उपयोग करने का प्रयास करें, हमें बहुत सी एसक्यूएल कोड करने की आवश्यकता है। परिदृश्य हर जगह पाया जा सकता है, जैसे डेटाबेस रूपांतरण, माइग्रेशन, प्रशासन, आदि। इनमें से अधिकांश एसक्यूएल को केवल एक बार निष्पादित किया जाएगा और फिर कभी उपयोग नहीं किया जाएगा, प्रत्येक कॉलम नाम केवल समय की बर्बादी है। और एसक्यूएल के आविष्कार को केवल प्रोग्रामर के उपयोग के लिए मत भूलना।

आमतौर पर मैं उपसर्गों वाले कॉलम नामों के साथ एक उपयोगिता दृश्य बनाऊंगा, यहाँ 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;

3

मैं पूरी तरह से डुप्लिकेट फ़ील्ड नामों के बारे में आपकी समस्या को समझता हूं।

जब तक मैं इसे हल करने के लिए अपने स्वयं के फ़ंक्शन को कोडित नहीं करता, तब तक मुझे इसकी आवश्यकता थी। यदि आप 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;
}

2

इसके लिए कोई 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)

यह काम करेगा लेकिन सवाल मूर्खतापूर्ण है। सिर्फ एक यूनियन या सब-क्वेरी क्यों नहीं करते। आप क्यों शामिल होंगे और अभी भी स्तंभ नामों में तालिका उपसर्ग चाहते हैं?
D3vtr0n 5

कैड: जानकारी के लिए धन्यवाद, यह दिलचस्प है। दुर्भाग्य से, डेटाबेस को बनाना / बदलना मेरे मामले में एक विकल्प नहीं है। Devtron: यदि आप किसी ऑब्जेक्ट के विभिन्न गुणों के लिए क्वेरी से वापस आने वाली जानकारी को मैप करने का प्रयास कर रहे हैं, तो वह जानकारी बहुत उपयोगी हो जाती है।
foxdonut

1
कभी-कभी विभिन्न तालिकाओं में स्तंभ नाम समान होते हैं, लेकिन समान मान नहीं होते हैं। इसलिए उन्हें विचारों या व्युत्पन्न तालिकाओं (जिसमें सभी अद्वितीय स्तंभ नाम होने चाहिए) में अंतर करने के लिए उन्हें उपसर्ग करने की आवश्यकता है।
केड रूक्स

@ फ़्रेडरिक, आपके कोड को कहीं और रहना पड़ता है - यह कोड उत्पन्न करता है। फिर, यह विकास के दौरान एक बार या गतिशील रूप से रन टाइम पर किया जा सकता है।
केड रूक्स

1

दो तरीके हैं जो मैं इसे पुन: प्रयोज्य तरीके से बनाने के लिए सोच सकता हूं। एक आपके सभी स्तंभों का नाम बदलने के लिए उपसर्ग के साथ तालिका है जो वे आए हैं। मैंने इसे कई बार देखा है, लेकिन मुझे यह पसंद नहीं है। मुझे लगता है कि यह बेमानी है, बहुत टाइपिंग का कारण बनता है, और आप हमेशा उपनाम का उपयोग कर सकते हैं जब आपको एक अस्पष्ट नाम वाले स्तंभ नाम के मामले को कवर करने की आवश्यकता होती है।

दूसरा तरीका, जो मैं आपको अपनी स्थिति में करने की सलाह दूंगा यदि आप इसके माध्यम से देखने के लिए प्रतिबद्ध हैं, तो तालिका के अन्य नामों के लिए विचार बनाना है। फिर आप तालिकाओं के बजाय उन विचारों के खिलाफ जुड़ते हैं। इस तरह, यदि आप चाहें तो आप उपयोग करने के लिए स्वतंत्र हैं। यदि आप चाहें तो मूल कॉलम नामों के साथ मूल तालिकाओं का उपयोग करने के लिए स्वतंत्र हैं, और यह किसी भी बाद के प्रश्नों को लिखना आसान बनाता है क्योंकि आपने पहले ही विचारों में नाम बदलने का काम किया है।

अंत में, मैं स्पष्ट नहीं हूं कि आपको यह जानने की आवश्यकता है कि प्रत्येक स्तंभ किस तालिका से आया है। क्या यह बात है? अंतत: वे क्या मायने रखते हैं जो उनके डेटा में हैं। क्या UserID उपयोगकर्ता तालिका से आया है या UserQuestion तालिका वास्तव में मायने नहीं रखती है। यह निश्चित रूप से मायने रखता है, जब आपको इसे अपडेट करने की आवश्यकता होती है, लेकिन उस बिंदु पर आपको पहले से ही अपने स्कीमा को अच्छी तरह से पता होना चाहिए कि यह निर्धारित करना है।


"अंत में, मैं स्पष्ट नहीं हूं कि आपको यह जानने की आवश्यकता है कि प्रत्येक स्तंभ किस तालिका से आया है। क्या यह मामला है?" <- 11 साल बाद, एक उपयोग-मामला गो में संरचनात्मक स्कैनिंग है।
ली बेन्सन

1

या आप लाल गेट SQL रिफलेक्टर या SQL प्रॉम्प्ट का उपयोग कर सकते हैं, जो टैब बटन के एक क्लिक के साथ कॉलम सूची में आपके चयन * का विस्तार करता है।

तो आपके मामले में, अगर आप SELECT में * A JOIN B से टाइप करते हैं ... *, टैब बटन, वॉयला के अंत में जाएँ! आप एक सही बी से SELECT A.column1, A.column2, ...., B.column1, B.column2 देख पाएंगे।

हालांकि यह मुफ़्त नहीं है


1

खिचड़ी भाषा अलियासिंग के बिना ऐसा करते हैं, सिर्फ इसलिए, कि आप उस खंड में किसी फ़ील्ड का संदर्भ कैसे दे रहे हैं, यदि वह फ़ील्ड 2 या 3 तालिकाओं में मौजूद है, जिसमें आप शामिल हो रहे हैं? यह mysql के लिए अस्पष्ट होगा जिसे आप संदर्भित करने का प्रयास कर रहे हैं।


1

मैंने इसमें शामिल तालिकाओं में फ़ील्ड का नाम बदलकर मेरी एक समान समस्या हल की। हां, मुझे ऐसा करने का सौभाग्य मिला और मैं समझता हूं कि हर किसी के पास यह नहीं हो सकता। मैंने तालिका नाम का प्रतिनिधित्व करने वाली तालिका के भीतर प्रत्येक फ़ील्ड में उपसर्ग जोड़ा। इस प्रकार ओपी द्वारा तैनात एसक्यूएल अपरिवर्तित रहेगा -

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

और फिर भी अपेक्षित परिणाम दें - यह पहचानने में आसानी कि आउटपुट फ़ील्ड किस तालिका से संबंधित है।


0

चयन करें * आमतौर पर खराब कोड के लिए बनाता है, क्योंकि नए कॉलम जोड़े जाते हैं या स्तंभों के क्रम काफी बार बदलते हैं जो आमतौर पर बहुत सूक्ष्म तरीके से चयन * को तोड़ते हैं। इसलिए कॉलमों को सूचीबद्ध करना सही समाधान है।

अपनी क्वेरी कैसे करें, mysql के बारे में निश्चित नहीं है, लेकिन sqlserver में आप syscolumns से कॉलम नामों का चयन कर सकते हैं और गतिशील रूप से चयन क्लॉज का निर्माण कर सकते हैं।


बिंदु लिया गया है, लेकिन मेरे संदर्भ में, मुझे कुछ सामान्य और गतिशील की आवश्यकता है, इसलिए वास्तव में मेरा कोड नए कॉलमों को जोड़ा / पुन: व्यवस्थित किया जाएगा / आदि। मैं कॉलम को व्यक्तिगत रूप से सूचीबद्ध नहीं करना चाहता।
foxdonut

5
डायनामिकली सेलेक्ट करने के लिए syscolumns से चयन एक भयानक हैक है, और मैं इसे प्रोडक्शन में नहीं सुझाऊँगा।
जूलियट

0

यदि स्कीमा परिवर्तन के बारे में चिंतित हैं तो यह आपके लिए काम कर सकता है: 1. शामिल सभी तालिकाओं पर एक 'DESCRIBE तालिका' क्वेरी चलाएँ। 2. अपने चुने हुए उपनाम के साथ उपसर्ग किए गए स्तंभ नामों की एक स्ट्रिंग को गतिशील रूप से बनाने के लिए दिए गए फ़ील्ड नामों का उपयोग करें।


0

MySQL C-API का उपयोग करने वालों के लिए आपके प्रश्न का सीधा उत्तर है।

एसक्यूएल दिया:

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

फ़ील्ड पर ध्यान दें: कैटलॉग, टेबल, org_name

अब आप जानते हैं कि आपकी SQL में कौन से फ़ील्ड किस स्कीमा (उर्फ कैटलॉग) और टेबल से संबंधित हैं। यह बहु-तालिका sql क्वेरी से प्रत्येक क्षेत्र को सामान्य रूप से पहचानने के लिए पर्याप्त है, बिना किसी अन्य चीज के।

एक वास्तविक उत्पाद SqlYOG को इस तरह के मनोर में इस सटीक डेटा का उपयोग करने के लिए दिखाया जाता है कि वे पीके फ़ील्ड मौजूद होने पर मल्टी-टेबल जॉइन की प्रत्येक तालिका को स्वतंत्र रूप से अपडेट करने में सक्षम हैं।


0

इस समाधान से विकास , यह है कि मैं इस समस्या को कैसे हल करूंगा:

सबसे पहले सभी 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 सर्वर में किया जाता है। लेकिन यह कोड SQL सर्वर में बिल्कुल काम नहीं करता है क्योंकि USING समर्थित नहीं है।

कृपया टिप्पणी करें कि क्या आप इस कोड को उदाहरण के लिए MySQL का परीक्षण / सुधार कर सकते हैं।


0

हाल ही में NodeJS और Postgres में इस मुद्दे पर भाग गया।

ईएस 6 दृष्टिकोण

ऐसी कोई आरडीबीएमएस सुविधाएँ नहीं हैं, जिनके बारे में मुझे पता है कि यह कार्यशीलता प्रदान करती है, इसलिए मैंने अपने सभी क्षेत्रों में एक ऑब्जेक्ट बनाया, जैसे:

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

एक तालिका नाम के साथ तारों को एक साथ जोड़ने के लिए एक reducer परिभाषित:

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

मैंने नोड में डमी या प्रहरी कॉलम का उपयोग करने के सुझाव के आधार पर एक समाधान लागू किया । आप इसका उपयोग 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

मैं क्या करता हूँ प्रक्रिया को संक्षिप्त करने के लिए एक्सेल का उपयोग करता हूं। उदाहरण के लिए, पहले मैं * का चयन करता हूं और सभी कॉलम प्राप्त करता हूं, उन्हें एक्सेल में पेस्ट करता हूं। फिर कॉलम को घेरने के लिए मुझे जो कोड चाहिए, उसे लिखें। मान लें कि मुझे स्तंभों के समूह में विज्ञापन करने की आवश्यकता है। मेरे कॉलम में मेरे फ़ील्ड्स होंगे और कॉलम B में "as_ prev_" और कॉलम c में मेरे फ़ील्ड्स फिर से होंगे। कॉलम d में मेरे पास एक कॉलम होगा।

फिर कॉलम ई में कॉनेटनेट का उपयोग करें और उन्हें एक साथ मर्ज करें, जिससे रिक्त स्थान शामिल करना सुनिश्चित हो सके। फिर इसे अपने sql कोड में काटें और पेस्ट करें। मैंने इस विधि का उपयोग उसी फ़ील्ड और अन्य लंबे कोड्स के लिए केस स्टेटमेंट बनाने के लिए किया है, जो मुझे प्रत्येक फ़ील्ड के लिए मल्टीहेड फ़ील्ड टेबल में करने की आवश्यकता है।


0

पोस्टग्रेज में, मैं json ऑब्जेक्ट्स को वापस करने के लिए json फंक्शंस का उपयोग करता हूं .... फिर, क्वेरी करने के बाद, मैं json_decode फ़ील्ड्स को _json प्रत्यय देता हूं।

अर्थात:

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

फिर PHP में (या किसी अन्य भाषा में), मैं लौटे हुए कॉलम और json_decode () के माध्यम से लूप करता हूं यदि उनके पास "_json" प्रत्यय है (प्रत्यय को हटाते हुए भी। अंत में, मुझे "tab1" नामक एक ऑब्जेक्ट मिलता है)। tab1 फ़ील्ड, और एक अन्य जिसे "tab2" कहा जाता है, जिसमें सभी tab2 फ़ील्ड शामिल हैं।


-1

PHP 7.2 + MySQL / मारियाब

MySQL आपको एक ही नाम के साथ कई फ़ील्ड भेजेगा। यहां तक ​​कि टर्मिनल क्लाइंट में भी। लेकिन यदि आप एक सहयोगी सरणी चाहते हैं, तो आपको चाबी खुद बनानी होगी।

मूल के लिए @axelbrz को धन्यवाद। मैंने इसे नए php में पोर्ट किया है और इसे थोड़ा साफ किया है:

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'));
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.