sql - এসকিউএল সার্ভারে একক পাঠ্য স্ট্রিংয়ের মধ্যে একাধিক সারি থেকে কীভাবে পাঠ্য সংযোজন করবেন?




sql-server csv (20)

তিনটি সারি সহ নাম ধারণ করে একটি ডাটাবেস টেবিল বিবেচনা করুন:

Peter
Paul
Mary

Peter, Paul, Mary একক স্ট্রিংয়ে এটি চালু করার একটি সহজ উপায় কি?


ধারা দ্বারা একটি আদেশ উপস্থিত থাকলে এই উত্তর অপ্রত্যাশিত ফলাফল ফিরে আসতে পারে। সামঞ্জস্যপূর্ণ ফলাফলের জন্য, অন্য উত্তরগুলিতে বিস্তারিত FOR XML PATH পদ্ধতিগুলির একটি ব্যবহার করুন।

COALESCE ব্যবহার করুন:

DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + Name 
FROM People

শুধু কিছু ব্যাখ্যা (এই উত্তর তুলনামূলকভাবে নিয়মিত মতামত পেতে বলে মনে হচ্ছে):

  • Coalesce সত্যিই একটি সহায়ক প্রতারণা যে দুটি জিনিস সম্পাদন করে:

1) একটি খালি স্ট্রিং মান দিয়ে @Names আরম্ভ করার দরকার নেই।

2) শেষে একটি অতিরিক্ত বিভাজক বন্ধ করার প্রয়োজন নেই।

  • উপরের সারির একটি নিল নাম মান রয়েছে যদি উপরের সমাধানটি ভুল ফলাফল দেবে (যদি একটি নুল থাকে , NULL সেই সারির পরে @Names তৈরি করবে এবং পরবর্তী সারিটি খালি স্ট্রিং হিসাবে আবার শুরু হবে। দুটি সমাধান:
DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + Name
FROM People
WHERE Name IS NOT NULL

বা:

DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + 
    ISNULL(Name, 'N/A')
FROM People

আপনি যে আচরণ চান তা নির্ভর করে (প্রথম বিকল্পটি কেবল NULL আউট ফিল্টার করে, দ্বিতীয় বিকল্পটি তাদের একটি মার্কার বার্তা সহ [তালিকায় 'N / A' প্রতিস্থাপিত করে) যা তাদের জন্য উপযুক্ত।


এসকিউএল সার্ভার 2017+ এবং এসকিউএল আজর: STRING_AGG

এসকিউএল সার্ভারের পরবর্তী সংস্করণ থেকে শুরু করে, আমরা অবশেষে কোনও পরিবর্তনশীল বা এক্সএমএল ডিকচারি অবলম্বন ছাড়াই সারি জুড়ে সংযোজন করতে পারি।

STRING_AGG (ট্র্যাক্ট্যাক্ট-এসকিউএল)

গ্রুপ ছাড়া

SELECT STRING_AGG(Name, ', ') AS Departments
FROM HumanResources.Department;

গ্রুপিং সঙ্গে:

SELECT GroupName, STRING_AGG(Name, ', ') AS Departments
FROM HumanResources.Department
GROUP BY GroupName;

গ্রুপিং এবং সাব-সাজানোর সঙ্গে

SELECT GroupName, STRING_AGG(Name, ', ') WITHIN GROUP (ORDER BY Name ASC) AS Departments
FROM HumanResources.Department 
GROUP BY GroupName;

MySQL এ একটি ফাংশন রয়েছে, Group_Concat , যা আপনাকে একাধিক সারির মানগুলি সংহত করতে দেয়। উদাহরণ:

SELECT 1 AS a, GROUP_CONCAT(name ORDER BY name ASC SEPARATOR ', ') AS people 
FROM users 
WHERE id IN (1,2,3) 
GROUP BY a

Oracle 11g রিলিজ 2 LISTAGG ফাংশন সমর্থন করে। here ডকুমেন্টেশন।

COLUMN employees FORMAT A50

SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
FROM   emp
GROUP BY deptno;

    DEPTNO EMPLOYEES
---------- --------------------------------------------------
        10 CLARK,KING,MILLER
        20 ADAMS,FORD,JONES,SCOTT,SMITH
        30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

3 rows selected.

সতর্কতা

ফলাফল স্ট্রিং 4000 অক্ষরের উপর চলছে সম্ভাবনা আছে যদি এই ফাংশন বাস্তবায়ন সতর্কতা অবলম্বন করা হবে। এটি একটি ব্যতিক্রম নিক্ষেপ করা হবে। যদি এই ক্ষেত্রে হয় তবে আপনাকে ব্যতিক্রমটি হ্যান্ডেল করতে হবে অথবা আপনার নিজস্ব ফাংশনটি রোল করতে হবে যা সংযুক্ত স্ট্রিংকে 4000 অক্ষর অতিক্রম করতে বাধা দেয়।


Postgres অ্যারে সন্ত্রস্ত। উদাহরণ:

কিছু পরীক্ষা তথ্য তৈরি করুন:

postgres=# \c test
You are now connected to database "test" as user "hgimenez".
test=# create table names (name text);
CREATE TABLE                                      
test=# insert into names (name) values ('Peter'), ('Paul'), ('Mary');                                                          
INSERT 0 3
test=# select * from names;
 name  
-------
 Peter
 Paul
 Mary
(3 rows)

একটি অ্যারে তাদের একত্রিত করুন:

test=# select array_agg(name) from names;
 array_agg     
------------------- 
 {Peter,Paul,Mary}
(1 row)

অ্যারে একটি কমা সীমানা স্ট্রিং রূপান্তর করুন:

test=# select array_to_string(array_agg(name), ', ') from names;
 array_to_string
-------------------
 Peter, Paul, Mary
(1 row)

সম্পন্ন

PostgreSQL 9.0 থেকে এটি আরও সহজ ।


SQL সার্ভার vNext এ এটি STRING_AGG ফাংশনের সাথে তৈরি করা হবে, এখানে এটি সম্পর্কে আরও পড়তে হবে: https://msdn.microsoft.com/en-us/library/mt790580.aspx


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

নীচে একটি উদাহরণ যা SQL সার্ভার "Info_Schema.Columns" টেবিল ব্যবহার করে। এই সমাধান ব্যবহার করে, কোন টেবিল তৈরি করা বা তথ্য যোগ করা প্রয়োজন। এই উদাহরণটি ডাটাবেসের সকল সারণির জন্য কলামের নামের একটি কমা দ্বারা পৃথক তালিকা তৈরি করে।

SELECT
    Table_Name
    ,STUFF((
        SELECT ',' + Column_Name
        FROM INFORMATION_SCHEMA.Columns Columns
        WHERE Tables.Table_Name = Columns.Table_Name
        ORDER BY Column_Name
        FOR XML PATH ('')), 1, 1, ''
    )Columns
FROM INFORMATION_SCHEMA.Columns Tables
GROUP BY TABLE_NAME 

আপনাকে এমন একটি পরিবর্তনশীল তৈরি করতে হবে যা আপনার চূড়ান্ত ফলাফলটি ধরে রাখবে এবং এতে পছন্দ করবে।

সবচেয়ে সহজ সমাধান

DECLARE @char VARCHAR(MAX);

SELECT @char = COALESCE(@char + ', ' + [column], [column]) 
FROM [table];

PRINT @char;

আপনি nulls সঙ্গে মোকাবেলা করতে চান, তাহলে আপনি প্রথম বিভাগের কাছাকাছি একটি কোলাস যোগ করে বা অন্য কয়লা যোগ করে এটি করতে পারেন।

DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(COALESCE(@Names + ', ', '') + Name, @Names) FROM People

আমার বাড়িতে একটি এসকিউএল সার্ভারের অ্যাক্সেস নেই, তাই আমি এখানে সিনট্যাক্সে অনুমান করছি, তবে এটি কম বা কম:

DECLARE @names VARCHAR(500)

SELECT @names = @names + ' ' + Name
FROM Names

আমি সাধারণত এসকিউএল সার্ভারে স্ট্রিংগুলিকে একত্রিত করার জন্য এটি পছন্দ করে নির্বাচন করি:

with lines as 
( 
  select 
    row_number() over(order by id) id, -- id is a line id
    line -- line of text.
  from
    source -- line source
), 
result_lines as 
( 
  select 
    id, 
    cast(line as nvarchar(max)) line 
  from 
    lines 
  where 
    id = 1 
  union all 
  select 
    l.id, 
    cast(r.line + N', ' + l.line as nvarchar(max))
  from 
    lines l 
    inner join 
    result_lines r 
    on 
      l.id = r.id + 1 
) 
select top 1 
  line
from
  result_lines
order by
  id desc

এই উত্তর সার্ভার কাজ কিছু বিশেষাধিকার প্রয়োজন হবে।

Assemblies জন্য একটি ভাল বিকল্প। সাইটগুলি কীভাবে তৈরি করবেন তা ব্যাখ্যা করে এমন অনেক সাইট রয়েছে। আমি মনে করি এক খুব ভাল ব্যাখ্যা এই one

যদি আপনি চান, আমি ইতিমধ্যে সমাবেশ তৈরি করেছি, এবং here DLL ডাউনলোড করা সম্ভব।

একবার আপনি এটি ডাউনলোড করলে, আপনার SQL সার্ভারে নিম্নলিখিত স্ক্রিপ্টটি চালাতে হবে:

CREATE Assembly concat_assembly 
   AUTHORIZATION dbo 
   FROM '<PATH TO Concat.dll IN SERVER>' 
   WITH PERMISSION_SET = SAFE; 
GO 

CREATE AGGREGATE dbo.concat ( 

    @Value NVARCHAR(MAX) 
  , @Delimiter NVARCHAR(4000) 

) RETURNS NVARCHAR(MAX) 
EXTERNAL Name concat_assembly.[Concat.Concat]; 
GO  

sp_configure 'clr enabled', 1;
RECONFIGURE

সমাবেশের পথ সার্ভারে অ্যাক্সেসযোগ্য হতে পারে তা পর্যবেক্ষণ করুন। যেহেতু আপনি সফলভাবে সমস্ত পদক্ষেপ সম্পন্ন করেছেন, তাই আপনি ফাংশন ব্যবহার করতে পারেন:

SELECT dbo.Concat(field1, ',')
FROM Table1

আশা করি এটা সাহায্য করবে!!!


এই পদ্ধতিটি তার এনপিএটিএইচ ফাংশনটি ব্যবহার করে শুধুমাত্র তারডটা এস্টার ডেটাবেসে প্রযোজ্য।

আবার, আমরা টেবিল ছাত্র আছে

SubjectID       StudentName
----------      -------------
1               Mary
1               John
1               Sam
2               Alaina
2               Edward

তারপর NPATH এর সাথে এটি শুধুমাত্র একক নির্বাচন:

SELECT * FROM npath(
  ON Students
  PARTITION BY SubjectID
  ORDER BY StudentName
  MODE(nonoverlapping)
  PATTERN('A*')
  SYMBOLS(
    'true' as A
  )
  RESULT(
    FIRST(SubjectID of A) as SubjectID,
    ACCUMULATE(StudentName of A) as StudentName
  )
);

ফলাফল:

SubjectID       StudentName
----------      -------------
1               [John, Mary, Sam]
2               [Alaina, Edward]

একটি recursive সিটিই সমাধান প্রস্তাব করা হয়, কিন্তু কোন কোড দেওয়া। নিচের কোডটি একটি পুনরাবৃত্তিমূলক CTE- এর একটি উদাহরণ - মনে রাখবেন যে যদিও ফলাফলটি মিলছে তবে তথ্যটি পুরোপুরি বর্ণিত বর্ণনাটির সাথে মিলছে না, যেমন আমি অনুমান করছি যে আপনি সারির গোষ্ঠীতে এটি করতে চান টেবিলে সারি। টেবিলে সমস্ত সারি মেলে এটি পরিবর্তন পাঠক জন্য ব্যায়াম হিসাবে বামে হয়।

;with basetable as 
(   SELECT id, CAST(name as varchar(max))name, 
        ROW_NUMBER() OVER(Partition By id     order by seq) rw, 
        COUNT(*) OVER (Partition By id) recs 
FROM (VALUES (1, 'Johnny', 1), (1,'M', 2), 
                  (2,'Bill', 1), (2, 'S.', 4), (2, 'Preston', 5), (2, 'Esq.', 6),
        (3, 'Ted', 1), (3,'Theodore', 2), (3,'Logan', 3),
                  (4, 'Peter', 1), (4,'Paul', 2), (4,'Mary', 3)

           )g(id, name, seq)
),
rCTE as (
    SELECT recs, id, name, rw from basetable where rw=1
    UNION ALL
    SELECT b.recs, r.ID, r.name +', '+ b.name name, r.rw+1
    FROM basetable b
         inner join rCTE r
    on b.id = r.id and b.rw = r.rw+1
)
SELECT name FROM rCTE
WHERE recs = rw and ID=4

এমএস এসকিউএল সার্ভারে XML data() কমান্ডের মাধ্যমে এখনো দেখা যায় না এমন একটি পদ্ধতি হল:

NameList নামক টেবিল অনুমান করুন FName নামে একটি কলাম সহ,

SELECT FName + ', ' AS 'data()' 
FROM NameList 
FOR XML PATH('')

আয়:

"Peter, Paul, Mary, "

শুধুমাত্র অতিরিক্ত কমা সঙ্গে মোকাবিলা করা আবশ্যক।

সম্পাদনা: @ এন। রিলায়িং এর মন্তব্য থেকে গৃহীত হিসাবে, আপনি অনুসরণকারী কমা অপসারণ করতে নিচের পদ্ধতিটি ব্যবহার করতে পারেন। একই টেবিল এবং কলামের নাম অনুমান করা হচ্ছে:

STUFF(REPLACE((SELECT '#!' + LTRIM(RTRIM(FName)) AS 'data()' FROM NameList
FOR XML PATH('')),' #!',', '), 1, 2, '') as Brands

ওরাকল ডিবিগুলির জন্য, এই প্রশ্নটি দেখুন: কীভাবে একাধিক সারিগুলি সংরক্ষণ করা পদ্ধতি তৈরি না করে ওরাকলের মধ্যে একত্রিত করা যায়?

সেরা উত্তর @ ইমানুয়েল দ্বারা প্রদর্শিত হয়, অন্তর্নির্মিত LISTAGG () ফাংশন ব্যবহার করে, ও ওরাকল 11 জি রিলিজ 2 এবং পরবর্তীতে উপলব্ধ।

SELECT question_id,
   LISTAGG(element_id, ',') WITHIN GROUP (ORDER BY element_id)
FROM YOUR_TABLE;
GROUP BY question_id

যেমন @ ব্যবহারকারী 762952 উল্লেখ করেছে, ও ওরাকলের ডকুমেন্টেশন অনুসারে http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php , WM_CONCAT () ফাংশনটিও একটি বিকল্প। এটি স্থিতিশীল বলে মনে হচ্ছে, তবে ওরাকল স্পষ্টভাবে যেকোনো অ্যাপ্লিকেশন এসকিউএল এর জন্য এটি ব্যবহার করার প্রস্তাব দেয়, তাই আপনার নিজের ঝুঁকিতে ব্যবহার করুন।

অন্যথায়, আপনি আপনার নিজস্ব ফাংশন লিখতে হবে; উপরে ও ওরাকল নথিটি কীভাবে তা করতে একটি নির্দেশিকা রয়েছে।


কোনও অতিরিক্ত কমা ছাড়াই ব্যবহারযোগ্য সমাধান:

select substring(
        (select ', '+Name AS 'data()' from Names for xml path(''))
       ,3, 255) as "MyList"

একটি খালি তালিকা নুল মান হবে। সাধারণত আপনি একটি টেবিল কলাম বা প্রোগ্রাম পরিবর্তনশীল মধ্যে তালিকা সন্নিবেশ করা হবে: আপনার প্রয়োজন 255 সর্বোচ্চ দৈর্ঘ্য সামঞ্জস্য।

(দিওয়াকার ও জেনস ফ্রেন্ডসেন ভাল উত্তর দিয়েছেন, তবে উন্নতির প্রয়োজন।)


নিল মান এড়াতে আপনি CONCAT ব্যবহার করতে পারেন ()

DECLARE @names VARCHAR(500)
SELECT @names = CONCAT(@names, ' ', name) 
FROM Names
select @names

MySQL সম্পূর্ণ উদাহরণ:

আমাদের ব্যবহারকারী রয়েছে যা অনেক তথ্য ধারণ করতে পারে এবং আমরা একটি আউটপুট পেতে চাই, যেখানে আমরা একটি তালিকাতে সমস্ত ব্যবহারকারীদের ডেটা দেখতে পারি:

ফলাফল:

___________________________
| id   |  rowList         |
|-------------------------|
| 0    | 6, 9             |
| 1    | 1,2,3,4,5,7,8,1  |
|_________________________|

টেবিল সেটআপ:

CREATE TABLE `Data` (
  `id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;


INSERT INTO `Data` (`id`, `user_id`) VALUES
(1, 1),
(2, 1),
(3, 1),
(4, 1),
(5, 1),
(6, 0),
(7, 1),
(8, 1),
(9, 0),
(10, 1);


CREATE TABLE `User` (
  `id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


INSERT INTO `User` (`id`) VALUES
(0),
(1);

প্রশ্ন:

SELECT User.id, GROUP_CONCAT(Data.id ORDER BY Data.id) AS rowList FROM User LEFT JOIN Data ON User.id = Data.user_id GROUP BY User.id

DECLARE @Names VARCHAR(8000)
SELECT @name = ''
SELECT @Names = @Names + ',' + Names FROM People
SELECT SUBSTRING(2, @Names, 7998)

এই শুরুতে বিরাট কমা রাখে।

যাইহোক, যদি আপনার অন্য কলামের প্রয়োজন হয় বা CSV একটি শিশু টেবিল প্রয়োজন হয় তবে আপনাকে স্কলার ব্যবহারকারী নির্ধারিত ক্ষেত্র (UDF) এ এটি মোড়ানো প্রয়োজন।

আপনিও সিলেক্ট ক্লজে একটি সম্পর্কিত সম্পর্ক হিসাবে এক্সএমএল পথটি ব্যবহার করতে পারেন (তবে আমি কাজ করতে ফিরে যাওয়ার জন্য অপেক্ষা করতে হবে কারণ Google ঘরে কাজ করে না :-)





group-concat