পোস্টগ্রিএসকিউএল 'গ্রুপে' কোয়েরি দ্বারা স্ট্রিং ফিল্ডের স্ট্রিংগুলি কীভাবে সংযুক্ত করা যায়?


351

আমি কোয়েরি অনুসারে একটি গ্রুপের মধ্যে একটি ক্ষেত্রের স্ট্রিংগুলি সংযুক্ত করার একটি উপায় খুঁজছি। সুতরাং উদাহরণস্বরূপ, আমার একটি টেবিল রয়েছে:

ID   COMPANY_ID   EMPLOYEE
1    1            Anna
2    1            Bill
3    2            Carol
4    2            Dave

এবং আমি এই জাতীয় কিছু পাওয়ার জন্য কোম্পানী_দলে গ্রুপ করতে চেয়েছিলাম:

COMPANY_ID   EMPLOYEE
1            Anna, Bill
2            Carol, Dave

একটা বিল্ট-ইন করা হয় ফাংশন মাইএসকিউএল মধ্যে এই কাজ করতে group_concat


1
মার্কাস ডুরিংয়ের উত্তর প্রযুক্তিগতভাবে আরও ভাল।
pstanton

@ পেস্টান্টন, ডুরিংয়ের উত্তর 8.4 এবং নীচের পক্ষে আরও ভাল।
জ্যারেড বেক

এই প্রশ্নটি dba.stackex بدل . com এর জন্য আরও উপযুক্ত ।
ডেভ জার্ভিস

এই বৈধ উত্তর এখন হওয়া উচিত stackoverflow.com/a/47638417/243233
Jus12

উত্তর:


542

PostgreSQL 9.0 বা তার পরে:

পোস্টগ্রিসের সাম্প্রতিক সংস্করণগুলিতে (২০১০ সালের শেষের দিকে) string_agg(expression, delimiter)ফাংশন রয়েছে যা প্রশ্নটির অনুরোধটি ঠিক তাই করবে, এমনকি আপনাকে ডিলিমিটার স্ট্রিং নির্দিষ্ট করে দেয়:

SELECT company_id, string_agg(employee, ', ')
FROM mytable
GROUP BY company_id;

পোস্টগ্রিস 9.0 কোনও সামগ্রিক অভিব্যক্তিতে একটি ORDER BYধারা নির্দিষ্ট করার ক্ষমতাও যুক্ত করেছে ; অন্যথায়, অর্ডার অপরিজ্ঞাত সুতরাং আপনি এখন লিখতে পারেন:

SELECT company_id, string_agg(employee, ', ' ORDER BY employee)
FROM mytable
GROUP BY company_id;

বা প্রকৃতপক্ষে:

SELECT string_agg(actor_name, ', ' ORDER BY first_appearance)

PostgreSQL 8.4 বা তারপরে:

পোস্টগ্র্যাসকিউএল 8.4 (২০০৯ সালে) সামগ্রিক ফাংশনটিarray_agg(expression) প্রবর্তন করে যা মানগুলিকে অ্যারে রূপান্তর করে। তারপরে array_to_string()কাঙ্ক্ষিত ফলাফল দেওয়ার জন্য ব্যবহার করা যেতে পারে:

SELECT company_id, array_to_string(array_agg(employee), ', ')
FROM mytable
GROUP BY company_id;

string_agg প্রাক-8.4 সংস্করণের জন্য:

যদি কেউ এই 9-পূর্বের 9.0 ডাটাবেসগুলির জন্য একটি কম্প্যাটিবিলিটি শিমের সন্ধান করতে আসে, তবে ক্লজটি string_aggবাদে সমস্ত কিছু কার্যকর করা সম্ভব ORDER BY

সুতরাং নীচের সংজ্ঞা দিয়ে এটি 9.x পোস্টগ্রিস ডিবি-র মতো একই কাজ করবে:

SELECT string_agg(name, '; ') AS semi_colon_separated_names FROM things;

তবে এটি একটি সিনট্যাক্স ত্রুটি হবে:

SELECT string_agg(name, '; ' ORDER BY name) AS semi_colon_separated_names FROM things;
--> ERROR: syntax error at or near "ORDER"

PostgreSQL 8.3 এ পরীক্ষিত।

CREATE FUNCTION string_agg_transfn(text, text, text)
    RETURNS text AS 
    $$
        BEGIN
            IF $1 IS NULL THEN
                RETURN $2;
            ELSE
                RETURN $1 || $3 || $2;
            END IF;
        END;
    $$
    LANGUAGE plpgsql IMMUTABLE
COST 1;

CREATE AGGREGATE string_agg(text, text) (
    SFUNC=string_agg_transfn,
    STYPE=text
);

কাস্টম প্রকরণ (সমস্ত পোস্টগ্র্যাস সংস্করণ)

9.0 এর আগে, স্ট্রাকট্যান্ট স্ট্রিংগুলির জন্য কোনও অন্তর্নির্মিত সমষ্টিগত কার্য ছিল না। সবচেয়ে সহজ কাস্টম বাস্তবায়ন ( অনেকের মধ্যে এই মেইলিং তালিকা পোস্টে বাজদা গাবো দ্বারা প্রস্তাবিত ) হ'ল বিল্ট-ইন textcatফাংশন (যা ||অপারেটরের পিছনে রয়েছে ) ব্যবহার করা:

CREATE AGGREGATE textcat_all(
  basetype    = text,
  sfunc       = textcat,
  stype       = text,
  initcond    = ''
);

এখানে CREATE AGGREGATEডকুমেন্টেশন দেওয়া আছে।

এটি কেবল কোনও বিভাজক ছাড়া সমস্ত স্ট্রিং একসাথে আঠালো করে। শেষে না পেয়ে তাদের মধ্যে একটি "," প্রবেশ করানোর জন্য, আপনি নিজের কন্টেন্টেশন ফাংশন তৈরি করতে এবং এটি উপরের "টেক্সটক্যাট" এর বিকল্প হিসাবে রাখতে চাইতে পারেন। এখানে আমি একসাথে রেখেছি এবং 8.3.12 এ পরীক্ষা করেছি:

CREATE FUNCTION commacat(acc text, instr text) RETURNS text AS $$
  BEGIN
    IF acc IS NULL OR acc = '' THEN
      RETURN instr;
    ELSE
      RETURN acc || ', ' || instr;
    END IF;
  END;
$$ LANGUAGE plpgsql;

এই সংস্করণটি কমা আউটপুট দেবে এমনকি যদি সারিটির মানটি নালাগুলি বা খালি হয়, সুতরাং আপনি এরূপ আউটপুট পাবেন:

a, b, c, , e, , g

আপনি যদি আউটপুট দিতে অতিরিক্ত কমা অপসারণ করতে পছন্দ করেন:

a, b, c, e, g

তারপরে ELSIFএইভাবে ফাংশনে একটি চেক যুক্ত করুন :

CREATE FUNCTION commacat_ignore_nulls(acc text, instr text) RETURNS text AS $$
  BEGIN
    IF acc IS NULL OR acc = '' THEN
      RETURN instr;
    ELSIF instr IS NULL OR instr = '' THEN
      RETURN acc;
    ELSE
      RETURN acc || ', ' || instr;
    END IF;
  END;
$$ LANGUAGE plpgsql;

1
আমি পাঠ্য করতে এস এন্ড আর বার্চার করতে হয়েছিল (সর্বশেষ pgsql স্থিতিশীল) তবে এটি দুর্দান্ত!
কেভ

1
আপনি কেবল এসকিউএল এ ফাংশনটি লিখতে পারেন যা ইনস্টলেশনটির জন্য সহজ (plpgsql কে সুপারইউসার দ্বারা ইনস্টল করতে হবে)। উদাহরণ হিসাবে আমার পোস্ট দেখুন।
bortzmeyer

11
"স্ট্রিংগুলি একত্রিত করার জন্য কোনও অন্তর্নির্মিত সমষ্টিগত কার্য নেই" - আপনি কেন ব্যবহার করবেন না array_to_string(array_agg(employee), ',')?
pstanton

2
PostgreSQL 9.0 ফাংশনের জন্য +1। আপনার যদি 9-পূর্ব পূর্ব সম্পর্কে উদ্বিগ্ন হতে হয় তবে মার্কাসের উত্তরটি আরও ভাল।
ব্র্যাড কোচ

7
নোট করুন যে পোস্টগ্রিসের সাম্প্রতিক সংস্করণগুলিও Order Byসামগ্রিক ফাংশনের অভ্যন্তরে একটি ধারা দেয় , যেমনstring_agg(employee, ',' Order By employee)
IMSoP

98

পোস্টগ্রিস অন্তর্নির্মিত অ্যারে ফাংশন ব্যবহার সম্পর্কে কীভাবে? কমপক্ষে 8.4-এ এটি বক্সের বাইরে কাজ করে:

SELECT company_id, array_to_string(array_agg(employee), ',')
FROM mytable
GROUP BY company_id;

দুর্ভাগ্যক্রমে এটি গ্রিনপ্লাম (v8.2) এ আমাদের জন্য কাজ করে না। +1 সমস্ত একই
এককিস

গ্রিনপ্লাম ৪.৩.৪.১ (পোস্টগ্র্রেএসকিউএল ৮.২.১৫ এ নির্মিত) এ আমার জন্য দুর্দান্ত কাজ করে।
ফিলহিবস

19

পোস্টগ্রিএসকিউএল 9.0 থেকে আপনি স্ট্রিং_এজিজি নামে একত্রিত ফাংশনটি ব্যবহার করতে পারেন । আপনার নতুন এসকিউএল এর কিছু দেখতে পাওয়া উচিত:

SELECT company_id, string_agg(employee, ', ')
FROM mytable
GROUP BY company_id;


13

আমি উত্তরের জন্য কোনও ক্রেডিট দাবি করি না কারণ কিছু অনুসন্ধানের পরে আমি এটি পেয়েছি:

আমি যা জানিনা তা হ'ল পোস্টগ্র্যাস এসকিউএল আপনাকে ক্রিয়েট এগ্রিগেটের সাথে আপনার নিজস্ব সামগ্রিক ফাংশনগুলি সংজ্ঞায়িত করতে দেয়

পোস্টগ্রাইএসকিউএল তালিকার এই পোস্টটি দেখায় যে যা প্রয়োজন তা করার জন্য কোনও ফাংশন তৈরি করা কতটা তুচ্ছ:

CREATE AGGREGATE textcat_all(
  basetype    = text,
  sfunc       = textcat,
  stype       = text,
  initcond    = ''
);

SELECT company_id, textcat_all(employee || ', ')
FROM mytable
GROUP BY company_id;

7

ইতিমধ্যে উল্লিখিত হিসাবে, আপনার নিজস্ব সমষ্টিগত ফাংশন তৈরি করা সঠিক জিনিস। এখানে আমার সংমিশ্রণ সামগ্রিক ফাংশন (আপনি ফরাসি ভাষায় বিশদ জানতে পারেন ):

CREATE OR REPLACE FUNCTION concat2(text, text) RETURNS text AS '
    SELECT CASE WHEN $1 IS NULL OR $1 = \'\' THEN $2
            WHEN $2 IS NULL OR $2 = \'\' THEN $1
            ELSE $1 || \' / \' || $2
            END; 
'
 LANGUAGE SQL;

CREATE AGGREGATE concatenate (
  sfunc = concat2,
  basetype = text,
  stype = text,
  initcond = ''

);

এবং তারপরে এটি ব্যবহার করুন:

SELECT company_id, concatenate(employee) AS employees FROM ...

5

আপনি 8.4-তে উন্নীত হলে এই সর্বশেষ ঘোষণার তালিকার স্নিপেট আগ্রহী হতে পারে:

8.4 একটি অতি-কার্যকর নেটিভ সাথে উপস্থিত না হওয়া পর্যন্ত আপনি পোস্টগ্রিজ এসকিউএল ডকুমেন্টেশনে অ্যারে_একসিএম ডকুমেন্টেশনে কোনও কলামটি অ্যারেতে রোল করার জন্য যোগ করতে পারেন, যা পরে অ্যাপ্লিকেশন কোড দ্বারা ব্যবহার করা যেতে পারে, বা বিন্যাসে অ্যারে_ টো স্ট্রিং () এর সাথে মিলিত হতে পারে এটি একটি তালিকা হিসাবে:

http://www.postgresql.org/docs/current/static/xaggr.html

আমি 8.4 বিকাশকারী ডক্সের সাথে লিঙ্ক করব তবে তারা এখনও এই বৈশিষ্ট্যটির তালিকা করে না বলে মনে হয়।


5

পোস্টগ্র্রেস ডক্স ব্যবহার করে কেভের উত্তর অনুসরণ করা:

প্রথমে উপাদানগুলির একটি অ্যারে তৈরি করুন, তারপরে অন্তর্নির্মিত array_to_stringফাংশনটি ব্যবহার করুন ।

CREATE AGGREGATE array_accum (anyelement)
(
 sfunc = array_append,
 stype = anyarray,
 initcond = '{}'
);

select array_to_string(array_accum(name),'|') from table group by id;

5

স্ট্রিং সংযুক্তকরণের একটি কাস্টম সমষ্টিগত ফাংশন ব্যবহারের উপর এখনো আবার অনুসরণ: আপনার মনে রাখা উচিত যে নির্বাচন বিবৃতি কোনো আদেশ সারি স্থাপন করবে, তাই আপনি একটি উপ কি প্রয়োজন হবে দরকার নির্বাচন মধ্যে থেকে একটি সঙ্গে বিবৃতি দ্বারা আদেশ দফা এবং তারপরে একটি বহিরাগত স্ট্রিংগুলিকে একত্রিত করার জন্য ক্লজ দিয়ে একটি গ্রুপের সাথে নির্বাচন করুন :

SELECT custom_aggregate(MY.special_strings)
FROM (SELECT special_strings, grouping_column 
        FROM a_table 
        ORDER BY ordering_column) MY
GROUP BY MY.grouping_column

3

আমি এই পোস্টগ্রাইএসকিউএল ডকুমেন্টেশনটি সহায়ক বলে খুঁজে পেয়েছি: http://www.postgresql.org/docs/8.0/interactive/funitions-conditional.html

আমার ক্ষেত্রে, ক্ষেত্রটি খালি না থাকলে, তার চারপাশে বন্ধনী যুক্ত ক্ষেত্রকে সংযুক্ত করার জন্য আমি সরল এসকিউএল অনুসন্ধান করেছি।

select itemid, 
  CASE 
    itemdescription WHEN '' THEN itemname 
    ELSE itemname || ' (' || itemdescription || ')' 
  END 
from items;


0

সংস্করণ পোস্টগ্রিসকিউএল 9.0 এবং এর উপরে অনুসারে আপনি স্ট্রিং_এজিজি নামে একত্রিত ফাংশনটি ব্যবহার করতে পারেন। আপনার নতুন এসকিউএল এর কিছু দেখতে পাওয়া উচিত:

SELECT company_id, string_agg(employee, ', ')
    FROM mytable GROUP BY company_id;

0

আপনি ফর্ম্যাট ফাংশন ব্যবহার করতে পারেন। যা স্বতঃস্ফূর্তভাবে নিজে নিজেই পাঠ্য, প্রকরণ ইত্যাদির ধরণের রূপান্তর সম্পর্কেও যত্ন নিতে পারে।

create or replace function concat_return_row_count(tbl_name text, column_name text, value int)
returns integer as $row_count$
declare
total integer;
begin
    EXECUTE format('select count(*) from %s WHERE %s = %s', tbl_name, column_name, value) INTO total;
    return total;
end;
$row_count$ language plpgsql;


postgres=# select concat_return_row_count('tbl_name','column_name',2); --2 is the value

1
স্ট্রিংয়ের মানগুলিকে একত্রিত করার জন্য এটি কীভাবে সম্পর্কিত?
a_horse_with_no_name

0

আমি জেটব্রেইনস রাইডারটি ব্যবহার করছি এবং এটি পুনরায় সম্পাদন করার জন্য উপরের উদাহরণগুলি থেকে ফলাফলগুলি অনুলিপি করা একটি ঝামেলা ছিল কারণ এটি জেএসএনে এটি সমস্তকে আবৃত করে বলে মনে হয়েছিল। এটি তাদের একক বিবৃতিতে যোগ দেয় যা চালানো সহজ

select string_agg('drop table if exists "' || tablename || '" cascade', ';') 
from pg_tables where schemaname != $$pg_catalog$$ and tableName like $$rm_%$$

0

আপনি যদি অ্যামাজন রেডশিফ্টে থাকেন, যেখানে স্ট্রিং_এজি সমর্থিত নয়, তালিকা্যাগ ব্যবহারের চেষ্টা করুন।

SELECT company_id, listagg(EMPLOYEE, ', ') as employees
FROM EMPLOYEE_table
GROUP BY company_id;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.