SQL: कुछ को छोड़कर सभी कॉलम का चयन करें


108

क्या SELECTकिसी तालिका में सभी स्तंभों का एक तरीका है , विशिष्ट लोगों को छोड़कर? एक तालिका से सभी गैर-ब्लॉब या गैर-ज्यामितीय स्तंभों को चुनने के लिए आईटी बहुत सुविधाजनक होगा।

कुछ इस तरह:

SELECT * -the_geom FROM segments;
  • मैंने एक बार सुना था कि इस कार्यक्षमता को जानबूझकर SQL मानक से बाहर रखा गया था क्योंकि तालिका में कॉलम जोड़ने से क्वेरी परिणामों में परिवर्तन होगा। क्या ये सच है? क्या तर्क मान्य है?
  • क्या कोई वर्कअराउंड है, खासकर PostgreSQL में?

वह कौन सा उपयोग-मामला है जिसके लिए आप कुछ को छोड़कर सभी कॉलम जानना चाहते हैं? क्या कुछ मैनुअल क्वेश्चन करते हुए ऑन-स्क्रीन दिखाना सिर्फ है? क्या यह एक कार्यक्रम का हिस्सा है?
जोनलो

2
6 सार्थक, लघु कॉलम (एक-la के साथ एक मेज name, age, sid) है कि स्क्रीन की चौड़ाई में अच्छी तरह से फिट बैठता है, एक लंबे द्विआधारी साथ geomस्तंभ। मैं ज्यामिति बाइनरी को छोड़कर सभी क्षेत्रों को क्वेरी करना चाहता हूं, और उनके नामों को एक-एक करके लिखना थकाऊ है।
एडम मटन

उस स्थिति में, यह उस उपकरण के साथ करने के लिए अधिक कुछ हो सकता है जिसे आप SQL के साथ इंटरैक्टिव क्वेरी के साथ उपयोग कर रहे हैं ...
joanolo

1
@joanolo सादा PostgreSQL खोल।
एडम मटन

3
यह इतना स्पष्ट दिखता है। कभी-कभी आप एक या दो कॉलम प्रिंट नहीं करना चाहते क्योंकि वे दिलचस्प नहीं होते हैं या आप केवल परिणाम तालिका को स्क्रीन पर फिट करना चाहते हैं (विशेषकर यदि कमांड लाइन क्लाइंट का उपयोग किया जाता है)। मुझे उम्मीद है कि एक वाक्यविन्यास की तरह होगाselect (!coluns2,!column5) from sometable;
gumkins

जवाबों:


54

ऐसी सुविधा न तो Postgres और न ही SQL Standard (AFAIK) में मौजूद है। मुझे लगता है कि यह एक बहुत ही दिलचस्प सवाल है, इसलिए मैं थोड़ा सा गुगली कर दिया और एक दिलचस्प लेख postgresonline.com पर आ गया ।

वे एक दृष्टिकोण दिखाते हैं जो सीधे स्कीमा से कॉलम का चयन करता है:

SELECT 'SELECT ' || array_to_string(ARRAY(SELECT 'o' || '.' || c.column_name
        FROM information_schema.columns As c
            WHERE table_name = 'officepark' 
            AND  c.column_name NOT IN('officeparkid', 'contractor')
    ), ',') || ' FROM officepark As o' As sqlstmt

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

मुझे यकीन है कि अन्य समाधान हैं, लेकिन मुझे लगता है कि वे सभी कुछ प्रकार के जादू स्कीमा-क्वेरिंग-फू को शामिल करेंगे।

BTW: SELECT * ...इस के साथ लापरवाह हो सकता है के रूप में प्रदर्शन दंड हो सकता है


ऐसे समारोह कैसे बनाएं? मुझे एक ऐसा फ़ंक्शन बनाने का कोई तरीका नहीं मिल सकता है जो एक अज्ञात क्वेरी लौटाता है जिसे मुझे हमेशा पहले से एक तालिका घोषित करनी होगी।
ePascoal

17

असली जवाब यह है कि आप सिर्फ व्यावहारिक रूप से नहीं कर सकते। यह दशकों से एक अनुरोधित विशेषता है और डेवलपर्स इसे लागू करने से इनकार करते हैं।

स्कीमा तालिकाओं को क्वेरी करने का सुझाव देने वाला लोकप्रिय उत्तर कुशलता से नहीं चल पाएगा क्योंकि पोस्टग्रेज ऑप्टिमाइज़र गतिशील कार्यों को एक ब्लैक बॉक्स मानता है (नीचे परीक्षण केस देखें)। इसका मतलब है कि इंडेक्स का इस्तेमाल नहीं किया जाएगा और जॉइन्स को समझदारी से नहीं किया जाएगा। आप कुछ प्रकार के मैक्रो सिस्टम जैसे m4 के साथ बहुत बेहतर होंगे। कम से कम यह ऑप्टिमाइज़र को भ्रमित नहीं करेगा (लेकिन यह अभी भी आपको भ्रमित कर सकता है।) कोड को फोर्क किए बिना और फीचर को स्वयं लिखने या प्रोग्रामिंग भाषा इंटरफ़ेस का उपयोग करने के बिना आप अटक गए हैं।

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

test=# create table atest (i int primary key);
CREATE TABLE
test=# insert into atest select generate_series(1,100000);
INSERT 0 100000

test=# create function get_table_column(name text) returns setof record as
$$
    declare r record;
    begin
    for r in execute 'select  * from ' || $1 loop
    return next r;
    end loop;
    return; 
    end; 
$$ language plpgsql; 

test=# explain analyze select i from atest where i=999999;
                                                      QUERY PLAN                                    
----------------------------------------------------------------------------------------------------
-------------------
 Index Only Scan using atest_pkey on atest  (cost=0.29..8.31 rows=1 width=4) (actual time=0.024..0.0
24 rows=0 loops=1)
   Index Cond: (i = 999999)
   Heap Fetches: 0
 Planning time: 0.130 ms
 Execution time: 0.067 ms
(5 rows)

test=# explain analyze
    select * from get_table_column('atest') as arowtype(i int) where i = 999999;
                                                        QUERY PLAN                                  
----------------------------------------------------------------------------------------------------
-----------------------
 Function Scan on get_table_column arowtype  (cost=0.25..12.75 rows=5 width=4) (actual time=92.636..
92.636 rows=0 loops=1)
   Filter: (i = 999999)
   Rows Removed by Filter: 100000
 Planning time: 0.080 ms
 Execution time: 95.460 ms
(5 rows)

जैसा कि आप देख सकते हैं कि फंक्शन कॉल पूरे टेबल को स्कैन करती है जबकि डायरेक्ट क्वेरी इंडेक्स ( 95.46 एमएस बनाम 00.07ms ) का उपयोग करती है । इस प्रकार के फंक्शन किसी भी प्रकार के जटिल क्वेरी को इंडेक्स का उपयोग करने या सही क्रम में टेबल से जुड़ने के लिए आवश्यक होते हैं। ।


1
दिलचस्प परिप्रेक्ष्य। यह निश्चित रूप से कोड के बजाय मानव उपयोगकर्ताओं के लिए एक विशेषता है (या इसलिए मुझे आशा करनी चाहिए!) इसलिए मैं ग्राहक को जिम्मेदार बनाने के बारे में बिंदु देख सकता हूं। संभवतः ऐसी चीजें जैसे एक्सटेंडेड डिस्प्ले (\ x ऑन) क्लाइंट में विशुद्ध रूप से लागू की जाती हैं और एक ही स्थान पर ऑमटिंग कॉलम को लागू किया जाना चाहिए।
अधिकतम मर्फी

13

यह वास्तव में कुछ संभव है PostgreSQL 9.4 के साथ शुरू जहां JSONB पेश किया गया था। मैं Google मानचित्र में सभी उपलब्ध विशेषताओं को दिखाने के बारे में इसी तरह के प्रश्न के बारे में विचार कर रहा था (जियोसन के माध्यम से)।

जॉच चैनल पर जॉटो ने JSONB से तत्व को हटाने का प्रयास करने का सुझाव दिया।

यहाँ विचार है

select the_geom,
  row_to_json(foo)::jsonb - 'the_geom'::text attributes
from (
  select * from
  segments
) foo

जब आपको अलग-अलग कॉलम के बजाय json मिलता है, तो यह वही था जो मैं चाहता था। शायद json को अलग-अलग कॉलम में वापस विस्तारित किया जा सकता है।


हाँ, शायद यहाँ से कुछ है, लेकिन मैं अभी तक काम करने के लिए यह नहीं मिला
chrismarx

6

एकमात्र तरीका जो आप कर सकते हैं (आपको यह नहीं कहना चाहिए) वह है जो डायनेमिक एसक्यूएल स्टेटमेंट का उपयोग करके है। यह आसान है (जैसे DrColossos ने लिखा है) सिस्टम के विचारों को क्वेरी करने के लिए और तालिका की संरचना को खोजने और उचित कथन बनाने के लिए।

पुनश्च: आप अपनी तालिका संरचना को जाने / लिखे बिना सभी / कुछ कॉलमों का चयन क्यों करना चाहेंगे?


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

तो केवल डायनेमिक sql आपको बहुत से टाइपिंग :-) से बचा सकता है।
मैरियन

हर कोई मानता है कि क्वेरी बनाने वाला वह है जिसने डेटाबेस डिज़ाइन किया है। :-) मान लीजिए कि आपको एक्सेल उत्पन्न करने के लिए बहुत सारे फ़ील्ड (30 से अधिक) के साथ एक पुराने डेटाबेस को क्वेरी करने की आवश्यकता है, लेकिन एक या दो फ़ील्ड हैं जिनके पास संवेदनशील जानकारी है जिसे आप वितरित नहीं करना चाहते हैं।
yucer

3

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

आप अपनी आवश्यकता से अधिक कॉलम खींचने लगेंगे।

क्या होगा अगर चयन में सम्मिलित का हिस्सा है

TableA (col1, col2, col3 .. coln) में डालें। सब कुछ चुनें, लेकिन tableB से 2 कॉलम

कॉलम मिलान गलत होगा और आपका इंसर्ट फेल हो जाएगा।

यह संभव है, लेकिन मैं अभी भी प्रत्येक चयनित कॉलम के लिए हर आवश्यक कॉलम लिखने की सलाह देता हूं, भले ही लगभग हर कॉलम आवश्यक हो।


यह दृष्टिकोण स्पष्ट रूप से प्रोग्रामिक रूप से गलत है, लेकिन यह SELECTs के लिए कंसोल क्वेरी के रूप में हानिरहित और उपयोगी है ।
एडम मटन

3

यदि आपका लक्ष्य बड़े डेटा मानों के साथ कॉलम प्रदर्शित न करके डिबगिंग के दौरान स्क्रीन से अव्यवस्था को दूर करना है, तो आप निम्नलिखित जानकारी का उपयोग कर सकते हैं:

(यदि आपके पास पहले से नहीं है तो "हस्टोर" कंट्राब पैकेज स्थापित करें: " CREATE EXTENSION hstore;")

Col1, col2, col3 के साथ तालिका "परीक्षण" के लिए, आप "col2" का मान प्रदर्शित करने के लिए अशक्त कर सकते हैं:

select (r).* from (select (test #= hstore('col2',null)) as r from test) s;

या, प्रदर्शित करने से पहले दो कॉलम को शून्य पर सेट करें:

select (r).* from (select (test #= hstore('col2',null) #= hstore('col1',null)) as r from test) s;

चेतावनी यह है कि "परीक्षण" एक तालिका होना चाहिए (उर्फ या सबसिलेट काम नहीं करेगा) क्योंकि रिकॉर्ड प्रकार को हस्टोर में फीड करना परिभाषित किया जाना चाहिए।


3

मेरे द्वारा अभी-अभी खोजा गया वर्कअराउंड है, लेकिन उसे R के भीतर से SQL क्वेरी भेजनी पड़ती है। यह R उपयोगकर्ताओं के लिए उपयोग की जा सकती है।

मूल रूप से dplyrपैकेज SQL (और विशेष रूप से PostgreSQL) प्रश्नों को भेजता है और -(column_name)तर्क को स्वीकार करता है।

तो आपका उदाहरण इस प्रकार लिखा जा सकता है:

select(segments, -(the_geom))

3

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

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

यह संभव है, एक सहायक फ़ंक्शन की सहायता से जो लंबी सामग्री की जगह लेता है null( textमेरे उदाहरण में कोई भी कॉलम, लेकिन आप इसे संशोधित करेंगे कि आप किस प्रकार को दबाना चाहते हैं):

create table my_table(foo integer, bar integer, baz text);
insert into my_table(foo,bar,baz) values (1,2,'blah blah blah blah blah blah'),(3,4,'blah blah');
select * from my_table;
फू | बार | baz                          
-: | -: | : ----------------------------
  1 | 2 | ब्ला ब्ला ब्ला ब्ला ब्ला
  3 | 4 | ब्ला ब्ला                    
create function f(ttype anyelement) returns setof anyelement as
$$
declare
  toid oid;
  tname text;
  nname text;
  cols text;
begin
  --
  select pg_type.oid, pg_namespace.nspname, pg_type.typname
  into toid, nname, tname
  from pg_type join pg_namespace on pg_namespace.oid=pg_type.typnamespace
  where pg_type.oid=pg_typeof(ttype);
  --
  select string_agg((case when data_type<>'text' 
                          then column_name 
                          else 'null::'||data_type||' "'||column_name||'"' end)
                   ,', ' order by ordinal_position)
  into cols
  from information_schema.columns 
  where table_schema=nname and table_name=tname;
  --
  return query execute 'select '||cols||' from '||nname||'.'||tname;
  --
end
$$ language plpgsql;
select * from f(null::my_table);
फू | बार | baz
-: | -: | : ---
  1 | 2 | नल 
  ३ | 4 | शून्य

यहाँ dbfiddle


2
  • एक आवेदन के नजरिए से, यह एक आलसी समाधान है। एप्लिकेशन को स्वचालित रूप से यह जानने की संभावना नहीं है कि नए कॉलम (एस) के साथ क्या करना है।

    डेटा ब्राउज़र एप्लिकेशन डेटा के लिए मेटाडेटा को क्वेरी कर सकते हैं और चलने वाले प्रश्नों से कॉलम को बाहर कर सकते हैं, या कॉलम के डेटा के सबसेट का चयन कर सकते हैं। जोड़े जाने पर नए BLOB को बाहर रखा जा सकता है। विशेष पंक्तियों के लिए BLOB डेटा का चयन माँग पर किया जा सकता है।

  • किसी भी SQL वैरिएंट में जो डायनेमिक क्वेरीज़ को सपोर्ट करता है, टेबल्स को मेटा मेटा डेटा पर क्वेरी का उपयोग करके बनाया जा सकता है। आपके इरादे के लिए, मैं नाम के बजाय टाइप के आधार पर कॉलम को बाहर करूंगा।


2

आप *SQL-VIEWS में कभी नहीं देखें ... \d any_viewअपनी जाँच करें psql। आंतरिक प्रतिनिधित्व के लिए एक (आत्मनिरीक्षण) प्रीप्रोसेसिंग हैं


यहाँ सभी चर्चा से पता चलता है कि इस मुद्दे को प्रस्ताव (प्रश्न और विचार विमर्श में निहित) प्रोग्रामर के लिए एक वाक्य रचना चीनी, नहीं एक वास्तविक "एसक्यूएल अनुकूलन मुद्दा" ... ठीक है, मेरा अनुमान है, यह प्रोग्रामर के 80% के लिए है।

तो " आत्मनिरीक्षण के साथ पूर्व-पार्सिंग " के रूप में लागू किया जा सकता है ... देखें कि जब आप SQL-VIEW के साथ घोषित करते हैं तो PostgreSQL क्या करता है SELECT *: VIEW-constructor *सभी कॉलमों की सूची (आत्मनिरीक्षण द्वारा और उस समय जो आप चलाते हैं, में रूपांतरित करता है बनाएँ स्रोत-कोड)।

क्रीएट व्यू और प्रीपे के लिए कार्यान्वयन

यह एक व्यवहार्य कार्यान्वयन है। tखेतों के साथ तालिका मान लीजिए (id serial, name text, the_geom geom)

CREATE VIEW t_full AS SELECT * FROM t;
-- is transformed into SELECT id,name,the_geom FROM t;

CREATE VIEW t_exp_geom AS SELECT * -the_geom FROM t;
-- or other syntax as EXCEPT the_geom
-- Will be transformed into SELECT id,name FROM t;

पूर्व कथन के लिए भी

... तो, यह संभव है, और है कि 80% प्रोग्रामर की जरूरत है, PREPARE और VIEWS के लिए एक वाक्यविन्यास चीनी!


नोट: निश्चित रूप से व्यवहार्य वाक्य रचना शायद नहीं है - column_name, अगर पोस्टग्रेसीक्यूएल में कुछ संघर्ष हैं, तो हम सुझाव दे सकते हैं EXCEPT column_name,
EXCEPT (column_name1, column_name2, ..., column_nameN)या अन्य।


1

यह एक उम्मीद है कि सभी कॉलमों को चुनने का मेरा कार्य है। मैंने postgresonline.com और postgresql tuturial और अन्य स्रोतों से विचारों को संयुक्त किया ।

CREATE TABLE phonebook(phone VARCHAR(32), firstname VARCHAR(32),
lastname VARCHAR(32), address VARCHAR(64));
INSERT INTO phonebook(phone, firstname, lastname, address) 
VALUES ('+1 123 456 7890', 'John', 'Doe', 'North America'), 
('+1 321 456 7890', 'Matti', 'Meikeläinen', 'Finland'), 
('+1 999 456 7890', 'Maija', 'Meikeläinen', 'Finland'), 
('+9 123 456 7890', 'John', 'Doe', 'Canada'), 
('+1 123 456 7890', 'John', 'Doe', 'Sweden'), 
('+1 123 456 7890', 'John', 'Doe2', 'North America');

drop function all_except_one(text,text);
CREATE OR REPLACE FUNCTION all_except_one(to_remove TEXT, table_name1 TEXT) 
RETURNS void AS $$

 DECLARE 
 rec_row RECORD;
 curs1 refcursor ;

 BEGIN
  --print column names:
  raise notice '%', ('|'|| ARRAY_TO_STRING(ARRAY(SELECT 
  COLUMN_NAME::CHAR(20) FROM INFORMATION_SCHEMA.COLUMNS WHERE
  TABLE_NAME=table_name1 AND COLUMN_NAME NOT IN (to_remove) ), 
  '|') ||'|') ; 

  OPEN curs1 FOR
  EXECUTE 'select table_1  from (SELECT ' || ARRAY_TO_STRING(ARRAY(
  SELECT COLUMN_NAME::VARCHAR(50) FROM INFORMATION_SCHEMA.COLUMNS 
  WHERE TABLE_NAME=table_name1 AND COLUMN_NAME NOT IN (to_remove)    
  ), ', ') || ' FROM ' || table_name1 || ' limit 30)   table_1 ';

  LOOP
  -- fetch row into the rec_row
  FETCH curs1 INTO rec_row;

  -- exit when no more row to fetch
  EXIT WHEN NOT FOUND;

  -- build and print the row output

  raise notice '%',(select'| '|| regexp_replace( array_to_string(
  array_agg(a::char(20)),'|'),'["\(.*\)]+',   '','g') ||'|'  from 
  unnest(string_to_array(replace(replace(replace(trim(rec_row::text,
  '()'),'"',''), ', ','|'),')',' '),',')) as a);

  END LOOP;

  -- Close the cursor

  CLOSE curs1;

  END; $$ LANGUAGE plpgsql;

select  all_except_one('phone','phonebook');

--output:
--NOTICE:  |firstname           |lastname            |address             |
--NOTICE:  | John               |Doe                 |North America       |
--NOTICE:  | Matti              |Meikeläinen         |Finland             |
--NOTICE:  | Maija              |Meikeläinen         |Finland             |
--NOTICE:  | John               |Doe                 |Canada              |
--NOTICE:  | John               |Doe                 |Sweden              |
--NOTICE:  | John               |Doe2                |North America       |
-- all_except_one 
-- ----------------
-- (1 row)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.