মাইক্রোসফ্ট এসকিউএল সার্ভার 2005 এ গ্রুপ_ক্যাঙ্কট মাইএসকিউএল ফাংশন সিমুলেট করে?


347

আমি মাইক্রোসফ্ট এসকিউএল সার্ভার 2005-এ একটি মাইএসকিউএল ভিত্তিক অ্যাপ্লিকেশন স্থানান্তরিত করার চেষ্টা করছি (পছন্দ অনুসারে নয়, তবে এটি জীবন)।

মূল অ্যাপ্লিকেশনটিতে, আমরা একটি উল্লেখযোগ্য ব্যতিক্রম সহ প্রায় পুরোপুরি এএনএসআই-এসকিউএল অনুগত বিবৃতি ব্যবহার করি - আমরা মাইএসকিউএল এর group_concatফাংশনটি প্রায়শই প্রায়শই ব্যবহার করি ।

group_concat, যাইহোক, এটি কি: কর্মীদের নাম এবং প্রকল্পগুলির একটি সারণী দেওয়া, ...

SELECT empName, projID FROM project_members;

আয়:

ANDY   |  A100
ANDY   |  B391
ANDY   |  X010
TOM    |  A100
TOM    |  A510

... এবং আপনি এখানে গ্রুপ_কোটাটের সাথে যা পান:

SELECT 
    empName, group_concat(projID SEPARATOR ' / ') 
FROM 
    project_members 
GROUP BY 
    empName;

আয়:

ANDY   |  A100 / B391 / X010
TOM    |  A100 / A510

সুতরাং আমি যা জানতে চাই: হ'ল এসকিউএল সার্ভারে কোনও ব্যবহারকারী-সংজ্ঞায়িত ফাংশন যা এর কার্যকারিতা অনুকরণ করে তা লিখতে, বলা সম্ভব group_concat?

আমার কাছে ইউডিএফ, সঞ্চিত প্রক্রিয়া, বা এর মতো আরও কিছু ব্যবহার করার অভিজ্ঞতা নেই, কেবল এসকিউএল, তাই দয়া করে খুব বেশি ব্যাখ্যার দিক থেকে ভুল করুন :)


বেশ কয়েকটি
সহজলভ্য

এটি একটি পুরানো প্রশ্ন, তবে আমি এখানে দেওয়া সিএলআর সমাধানটি পছন্দ করি ।
দিয়েগো



আপনি কীভাবে জানবেন যে তালিকাটি কোন অর্ডারটি তৈরি করা উচিত, উদাহরণস্বরূপ আপনি A100 / B391 / X010 দেখান তবে একটি সম্পর্কিত সম্পর্কিত ডাটাবেসে কোনও অন্তর্নিহিত আদেশ নেই এটি কেবল X010 / A100 / B391 বা অন্য কোনও সংমিশ্রণ হতে পারে।
স্টিভ ফোর্ড

উত্তর:


174

এটি করার কোনও সত্যই সহজ উপায় নেই। যদিও সেখানে প্রচুর ধারণা রয়েছে।

আমি খুঁজে পেয়েছি সেরা :

SELECT table_name, LEFT(column_names , LEN(column_names )-1) AS column_names
FROM information_schema.columns AS extern
CROSS APPLY
(
    SELECT column_name + ','
    FROM information_schema.columns AS intern
    WHERE extern.table_name = intern.table_name
    FOR XML PATH('')
) pre_trimmed (column_names)
GROUP BY table_name, column_names;

অথবা এমন একটি সংস্করণ যা সঠিকভাবে কাজ করে যদি ডেটাতে অক্ষর থাকতে পারে <

WITH extern
     AS (SELECT DISTINCT table_name
         FROM   INFORMATION_SCHEMA.COLUMNS)
SELECT table_name,
       LEFT(y.column_names, LEN(y.column_names) - 1) AS column_names
FROM   extern
       CROSS APPLY (SELECT column_name + ','
                    FROM   INFORMATION_SCHEMA.COLUMNS AS intern
                    WHERE  extern.table_name = intern.table_name
                    FOR XML PATH(''), TYPE) x (column_names)
       CROSS APPLY (SELECT x.column_names.value('.', 'NVARCHAR(MAX)')) y(column_names) 

1
এই উদাহরণটি আমার পক্ষে কাজ করেছে, তবে আমি অন্য একত্রিত করার চেষ্টা করেছি এবং এটি কার্যকর হয়নি, আমাকে একটি ত্রুটি দিয়েছে: "'প্রি-ট্রাইম্মড' পারস্পরিক সম্পর্কের নামটি এফআরওএম ক্লজে একাধিকবার নির্দিষ্ট করা হয়েছে।"
ফিলচুয়াং

7
'pre_trimmed' subquery জন্য কেবল একটি উপনাম। উপাস্যগুলির জন্য উপকরণগুলি প্রয়োজনীয় এবং এটিকে অনন্য হতে হবে, তাই অন্য সাবকিউয়ের জন্য একে অন্যরকম কিছুতে পরিবর্তন করুন ...
কোয়েন

2
এটি কি বিভ্রান্তিকর কলামের নাম হিসাবে আপনি টেবিলের নাম ছাড়াই একটি উদাহরণ দেখাতে পারেন?
এস। ম্যাসন

169

আমি পার্টিতে কিছুটা দেরি করতে পারি তবে এই পদ্ধতিটি আমার পক্ষে কাজ করে এবং COALESCE পদ্ধতির চেয়ে সহজ।

SELECT STUFF(
             (SELECT ',' + Column_Name 
              FROM Table_Name
              FOR XML PATH (''))
             , 1, 1, '')

1
এটি কেবলমাত্র মানগুলি কীভাবে সংঘবদ্ধ করতে হয় তা দেখায় - গ্রুপ_কনক্যাট তাদেরকে দলবদ্ধভাবে সংঘবদ্ধ করে তোলে, যা আরও চ্যালেঞ্জিং (এবং ওপিটির কী প্রয়োজন বলে মনে হয়)। এটি করার জন্য এসও 15154644 এর গৃহীত উত্তরটি দেখুন - যেখানে ক্লজটি সমালোচনা সংযোজন
ডিজেডেভ

@ ডিজেডেভ এই উত্তরটি উল্লেখ করছিলেন । অনুরূপ প্রশ্নের গৃহীত উত্তরও দেখুন ।
জন কামিংস

51

সম্ভবত এখন উপকারে আসতে খুব দেরি হয়ে গেছে, তবে এটি কি কাজগুলি করার সবচেয়ে সহজ উপায় নয়?

SELECT     empName, projIDs = replace
                          ((SELECT Surname AS [data()]
                              FROM project_members
                              WHERE  empName = a.empName
                              ORDER BY empName FOR xml path('')), ' ', REQUIRED SEPERATOR)
FROM         project_members a
WHERE     empName IS NOT NULL
GROUP BY empName

মজাদার. আমি ইতিমধ্যে প্রকল্পটি হাতে পেয়েছি, তবে আমি এই পদ্ধতিটি চেষ্টা করে দেখছি। ধন্যবাদ!
ড্যানএম

7
দুর্দান্ত কৌশল - কেবলমাত্র সমস্যাটি ফাঁকা স্থানের અટারগুলির জন্য এটি স্থানটি পৃথককারীকে প্রতিস্থাপন করবে।
মার্ক ইলিয়ট

মার্ক আমি নিজেই এ জাতীয় সমস্যার মুখোমুখি হয়েছি। দুর্ভাগ্যক্রমে, এমএসএসকিউএল সময় না পেয়ে এবং GROUP_CONCAT প্রবর্তন না করা পর্যন্ত, আমি এখানে যা প্রয়োজন তা পূরণ করতে সক্ষম হওয়া ওভারহেড-নিবিড় পদ্ধতিগুলির মধ্যে এটি সবচেয়ে কম।
জে হার্ডিমান

এর জন্য ধন্যবাদ! এখানে একটি এসকিউএল বেহালার এটা কাজ দেখাচ্ছে sqlfiddle.com/#!6/c5d56/3
fleed

42

এসকিউএল সার্ভার 2017 একটি নতুন সামগ্রিক ফাংশন প্রবর্তন করে

STRING_AGG ( expression, separator)

স্ট্রিং এক্সপ্রেশনগুলির মানকে সংঘবদ্ধ করে এবং তাদের মধ্যে পৃথককারী মান রাখে। স্ট্রিংয়ের শেষে বিভাজক যুক্ত করা হয় না।

সংক্ষিপ্ত উপাদানগুলি সংযোজন দ্বারা অর্ডার করা যেতে পারে WITHIN GROUP (ORDER BY some_expression)

2005-2016 সংস্করণের জন্য আমি সাধারণত গৃহীত উত্তরে XML পদ্ধতি ব্যবহার করি।

এটি তবে কিছু পরিস্থিতিতে ব্যর্থ হতে পারে। উদাহরণস্বরূপ, যদি ডেটা কনেকেটেট করা থাকে তবে CHAR(29)আপনি দেখতে পাচ্ছেন

এক্সএমএলের জন্য ডেটা সিরিয়ালাইজ করা যায়নি ... কারণ এটিতে একটি অক্ষর রয়েছে (0x001D) যা এক্সএমএলে অনুমোদিত নয়।

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

কোনও ভেরিয়েবলকে বরাদ্দ দেওয়ার পদ্ধতিটি গ্যারান্টিযুক্ত নয় এবং উত্পাদন কোডে এড়ানো উচিত।


এটি এখন অ্যাজুরে
en-

34

গিথুব-GROUP_CONCAT প্রকল্পটি দেখুন , আমি মনে করি আপনি যা যা অনুসন্ধান করছেন ঠিক তেমনই আমি করি:

এই প্রকল্পে এসকিউএলসিআরআর ব্যবহারকারী-সংজ্ঞায়িত সমষ্টি ফাংশন (এসকিউএলসিআরআর ইউডিএ) এর একটি সেট রয়েছে যা সম্মিলিতভাবে মাইএসকিউএল GROUP_CONCAT ফাংশনে অনুরূপ কার্যকারিতা সরবরাহ করে। প্রয়োজনীয় কার্যকারিতার উপর ভিত্তি করে সেরা পারফরম্যান্স নিশ্চিত করতে একাধিক ফাংশন রয়েছে ...


2
@ ম্যাক্সিওয়েট: ভোট দেওয়ার জন্য ক্লিক করার আগে অনেক লোক প্রশ্ন বা উত্তর মনোযোগ সহকারে পড়েন না। এটি তাদের ভুলের কারণে সরাসরি মালিকের পোস্টকে প্রভাবিত করে।
স্টিভ ল্যাম

দুর্দান্ত কাজ করে। আমি যে বৈশিষ্ট্যটি অনুপস্থিত তা হ'ল মাইএসকিউএল গ্রুপ_কনক্যাট () পছন্দ করতে পারে এমন কলামে বাছাই করার ক্ষমতা:GROUP_CONCAT(klascode,'(',name,')' ORDER BY klascode ASC SEPARATOR ', ')
জানুয়ারী

10

একাধিক প্রকল্প পরিচালক রয়েছে এমন প্রকল্পগুলি থেকে সমস্ত প্রকল্প পরিচালকের নাম যুক্ত করতে:

SELECT a.project_id,a.project_name,Stuff((SELECT N'/ ' + first_name + ', '+last_name FROM projects_v 
where a.project_id=project_id
 FOR
 XML PATH(''),TYPE).value('text()[1]','nvarchar(max)'),1,2,N''
) mgr_names
from projects_v a
group by a.project_id,a.project_name

9

নীচের কোডের সাথে আপনার স্থাপনার আগে আপনার প্রকল্পের বৈশিষ্ট্যগুলিতে PermissionLevel = বাহ্যিক সেট করতে হবে এবং "ALTER DATABASE ডাটাবেস_নাম SET চালিয়ে সুরক্ষার ঝুঁকি এবং বিকল্পগুলি [শংসাপত্রগুলির মতো] সম্পর্কে অন্য কোথাও পড়তে ভুলবেন না" হিসাবে বাহ্যিক কোডকে বিশ্বাস করার জন্য ডাটাবেসটি পরিবর্তন করতে হবে বিশ্বস্ততা চালু "।

using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using Microsoft.SqlServer.Server;

[Serializable]
[SqlUserDefinedAggregate(Format.UserDefined,
MaxByteSize=8000,
IsInvariantToDuplicates=true,
IsInvariantToNulls=true,
IsInvariantToOrder=true,
IsNullIfEmpty=true)]
    public struct CommaDelimit : IBinarySerialize
{


[Serializable]
 private class StringList : List<string>
 { }

 private StringList List;

 public void Init()
 {
  this.List = new StringList();
 }

 public void Accumulate(SqlString value)
 {
  if (!value.IsNull)
   this.Add(value.Value);
 }

 private void Add(string value)
 {
  if (!this.List.Contains(value))
   this.List.Add(value);
 }

 public void Merge(CommaDelimit group)
 {
  foreach (string s in group.List)
  {
   this.Add(s);
  }
 }

 void IBinarySerialize.Read(BinaryReader reader)
 {
    IFormatter formatter = new BinaryFormatter();
    this.List = (StringList)formatter.Deserialize(reader.BaseStream);
 }

 public SqlString Terminate()
 {
  if (this.List.Count == 0)
   return SqlString.Null;

  const string Separator = ", ";

  this.List.Sort();

  return new SqlString(String.Join(Separator, this.List.ToArray()));
 }

 void IBinarySerialize.Write(BinaryWriter writer)
 {
  IFormatter formatter = new BinaryFormatter();
  formatter.Serialize(writer.BaseStream, this.List);
 }
    }

দেখে মনে হচ্ছে এমন একটি কোয়েরি ব্যবহার করে এটি পরীক্ষা করেছি

SELECT 
 dbo.CommaDelimit(X.value) [delimited] 
FROM 
 (
  SELECT 'D' [value] 
  UNION ALL SELECT 'B' [value] 
  UNION ALL SELECT 'B' [value] -- intentional duplicate
  UNION ALL SELECT 'A' [value] 
  UNION ALL SELECT 'C' [value] 
 ) X 

এবং ফলন: এ, বি, সি, ডি


9

এগুলি চেষ্টা করেছিলাম তবে এমএস এসকিউএল সার্ভার ২০০৫ সালে আমার উদ্দেশ্যগুলির জন্য নিম্নলিখিতটি সবচেয়ে কার্যকর ছিল, যা আমি xaprbপেয়েছি

declare @result varchar(8000);

set @result = '';

select @result = @result + name + ' '

from master.dbo.systypes;

select rtrim(@result);

@ মার্ক হিসাবে আপনি উল্লেখ করেছেন যে এটি স্থানের অক্ষর যা আমার জন্য সমস্যা তৈরি করেছিল।


আমি মনে করি ইঞ্জিনটি এই পদ্ধতির সাথে কোনও অর্ডারকে সত্যিকার অর্থে গ্যারান্টি দেয় না, কারণ ভেরিয়েবলগুলি নির্বাহী পরিকল্পনার উপর নির্ভর করে ডেটা প্রবাহ হিসাবে গণনা করা হয়। এটি এখন পর্যন্ত বেশিরভাগ সময় কাজ বলে মনে হচ্ছে।
ফিলিউউ

6

জে হার্ডিমানের উত্তর সম্পর্কে, কীভাবে:

SELECT empName, projIDs=
  REPLACE(
    REPLACE(
      (SELECT REPLACE(projID, ' ', '-somebody-puts-microsoft-out-of-his-misery-please-') AS [data()] FROM project_members WHERE empName=a.empName FOR XML PATH('')), 
      ' ', 
      ' / '), 
    '-somebody-puts-microsoft-out-of-his-misery-please-',
    ' ') 
  FROM project_members a WHERE empName IS NOT NULL GROUP BY empName

যাইহোক, "અટর" ব্যবহারটি কি টাইপো বা আমি এখানে একটি ধারণা বুঝতে পারছি না?

যাইহোক, ধন্যবাদ অনেক লোকেরা এটি আমাকে বেশ কিছু সময় বাঁচিয়েছে :)


1
আপনি যদি আমাকে জিজ্ঞাসা করেন এবং উত্তর হিসাবে কিছুটা সহায়ক না হন তবে বরং বন্ধুত্বপূর্ণ উত্তর দিন।
টিম মিয়ারস

1
কেবল এখন এটি দেখছি ... আমি এটি কোনও গড় উপায়ে বোঝাতে চাইনি, সেই সময়ে আমি এসকিএল সার্ভারের সাথে খুব হতাশ ছিলাম (এখনও আছি)। এই পোস্টের উত্তরগুলি আসলেই সহায়ক ছিল; সম্পাদনা: কেন এটি বিটিডব্লিউ সহায়ক ছিল না? এটি আমার জন্য কৌশলটি করেছে
ব্যবহারকারীর 422190

1

আমার সহকর্মী গুগলারের জন্য, এখানে খুব সাধারণ প্লাগ-এন্ড-প্লে সমাধান রয়েছে যা কিছু সময়ের জন্য আরও জটিল সমাধানগুলির সাথে লড়াই করার পরে আমার পক্ষে কাজ করেছে:

SELECT
distinct empName,
NewColumnName=STUFF((SELECT ','+ CONVERT(VARCHAR(10), projID ) 
                     FROM returns 
                     WHERE empName=t.empName FOR XML PATH('')) , 1 , 1 , '' )
FROM 
returns t

লক্ষ্য করুন যে এটির স্ট্রিং হিসাবে যুক্ত করার জন্য আমাকে আইডিটিকে ভ্রচারে রূপান্তর করতে হয়েছিল। যদি আপনাকে এটি না করতে হয় তবে এখানে একটি আরও সহজ সংস্করণ:

SELECT
distinct empName,
NewColumnName=STUFF((SELECT ','+ projID
                     FROM returns 
                     WHERE empName=t.empName FOR XML PATH('')) , 1 , 1 , '' )
FROM 
returns t

এর জন্য সমস্ত ক্রেডিট এখানে যায়: https://social.msdn.microsoft.com/ Forums / sqlserver / en-US / 9508abc2-46e7-4186-b57f-7f368374e084 / replicating-groupconcat-function-of-mysql-in- SQL সার্ভার? ফোরাম = transactsql

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.