এসকিউএল সার্ভার: কলামগুলিতে সারি


128

কলামগুলিকে সারিতে রূপান্তর করতে মার্জিত (বা কোনও) সমাধানের সন্ধান করছেন।

এখানে একটি উদাহরণ রয়েছে: আমার কাছে নিম্নলিখিত স্কিমা সহ একটি টেবিল রয়েছে:

[ID] [EntityID] [Indicator1] [Indicator2] [Indicator3] ... [Indicator150]

ফলাফল হিসাবে আমি যা পেতে চাই তা এখানে:

[ID] [EntityId] [IndicatorName] [IndicatorValue]

এবং ফলাফল মানগুলি হবে:

1 1 'Indicator1' 'Value of Indicator 1 for entity 1'
2 1 'Indicator2' 'Value of Indicator 2 for entity 1'
3 1 'Indicator3' 'Value of Indicator 3 for entity 1'
4 2 'Indicator1' 'Value of Indicator 1 for entity 2'

এবং তাই ..

এটা কোনো কিছু হলো? টি-এসকিউএল কোথায় পাবেন এবং কীভাবে এটি করবেন সে সম্পর্কে আপনার কোনও পরামর্শ আছে?



এটি শেষে নীলফিটের সমাধান দিয়ে গেল। মার্জিত এবং ক্রিয়ামূলক। সবাইকে অনেক অনেক ধন্যবাদ
সের্গেই

উত্তর:


247

কলামগুলিকে সারিগুলিতে রূপান্তর করতে আপনি UNPIVOT ফাংশনটি ব্যবহার করতে পারেন :

select id, entityId,
  indicatorname,
  indicatorvalue
from yourtable
unpivot
(
  indicatorvalue
  for indicatorname in (Indicator1, Indicator2, Indicator3)
) unpiv;

দ্রষ্টব্য, আপনি যে কলামগুলির আনপাইভোট করছেন সেগুলির ডেটাটাইপগুলি অবশ্যই একই হতে হবে তাই আপনাকে আনপিবট প্রয়োগের আগে ডেটাটাইপগুলি রূপান্তর করতে হতে পারে।

CROSS APPLYকলামগুলি রূপান্তর করতে আপনি ইউনিয়ন সমস্তের সাথেও ব্যবহার করতে পারেন :

select id, entityid,
  indicatorname,
  indicatorvalue
from yourtable
cross apply
(
  select 'Indicator1', Indicator1 union all
  select 'Indicator2', Indicator2 union all
  select 'Indicator3', Indicator3 union all
  select 'Indicator4', Indicator4 
) c (indicatorname, indicatorvalue);

আপনার এসকিউএল সার্ভারের সংস্করণটির উপর নির্ভর করে আপনি ভলিউস ধারাটির সাথে ক্রস প্রয়োগও করতে পারেন:

select id, entityid,
  indicatorname,
  indicatorvalue
from yourtable
cross apply
(
  values
  ('Indicator1', Indicator1),
  ('Indicator2', Indicator2),
  ('Indicator3', Indicator3),
  ('Indicator4', Indicator4)
) c (indicatorname, indicatorvalue);

অবশেষে, যদি আনপিভট করার জন্য আপনার কাছে 150 টি কলাম থাকে এবং আপনি পুরো ক্যোয়ারিকে হার্ড-কোড করতে চান না, তবে আপনি ডায়নামিক এসকিউএল ব্যবহার করে এসকিএল স্টেটমেন্টটি তৈরি করতে পারেন:

DECLARE @colsUnpivot AS NVARCHAR(MAX),
   @query  AS NVARCHAR(MAX)

select @colsUnpivot 
  = stuff((select ','+quotename(C.column_name)
           from information_schema.columns as C
           where C.table_name = 'yourtable' and
                 C.column_name like 'Indicator%'
           for xml path('')), 1, 1, '')

set @query 
  = 'select id, entityId,
        indicatorname,
        indicatorvalue
     from yourtable
     unpivot
     (
        indicatorvalue
        for indicatorname in ('+ @colsunpivot +')
     ) u'

exec sp_executesql @query;

4
যাঁরা UNPIVOTএবং / বনাম সম্পর্কে আরও বাদাম এবং বোল্ট চান তাদের জন্য । APPLY, ব্র্যাড শুলজের এই 2010 ব্লগ পোস্টটি (এবং ফলো-অন ) সুন্দর (হ'ল)।
রাফিন

2
এমএসজি 67১6767, স্তর ১ 16, রাজ্য ১, লাইন 147 UNPIVOT তালিকায় নির্দিষ্ট অন্যান্য কলামগুলির ধরণের সাথে "ব্লাহাব্লাহ" কলামের ধরণের বিরোধ রয়েছে।
জেডিপিচাম

@ জেডিপিচাম আপনার যদি বিভিন্ন ডেটাটাইপ থাকে তবে আনপিবট সম্পাদন করার আগে আপনাকে সেগুলি একই ধরণের এবং দৈর্ঘ্যে রূপান্তর করতে হবে। এখানে যে সম্পর্কে আরও তথ্য
তারিন

এক্সএমএল পদ্ধতিতে একটি ত্রুটি রয়েছে কারণ এটি & gt ;, & lt; এর মতো এক্সএমএল কোডগুলি অনস্কেপ করতে ব্যর্থ; এবং & amp ;. এছাড়াও নিম্নোক্তভাবে পুনরায় লেখার মাধ্যমে পারফরম্যান্স উল্লেখযোগ্যভাবে উন্নত করা যেতে পারে: @colsUnpivot = স্টাফ নির্বাচন করুন (সিলেক্ট_নাম = 'আপনার টেবিল' যেখানে তথ্য_স্কেমমা কলামগুলি থেকে [পাঠ্য ()] হিসাবে বেছে নিন'colUnpivot = স্টাফ ('নির্বাচন করুন', '+' কোটেনইম (সি.কোলোম_নাম) select এবং সি.সি. কলাম_নম xML পাথ (''), টাইপ) এর জন্য 'সূচক%' এর মতো। মূল্য ('পাঠ্য () [1]', 'এনভারচর (সর্বোচ্চ)'), 1, 1, '')
রোজেমা

24

ভাল আপনার যদি 150 টি কলাম থাকে তবে আমি মনে করি UNPIVOT কোনও বিকল্প নয়। সুতরাং আপনি এক্সএমএল ট্রিক ব্যবহার করতে পারেন

;with CTE1 as (
    select ID, EntityID, (select t.* for xml raw('row'), type) as Data
    from temp1 as t
), CTE2 as (
    select
         C.id, C.EntityID,
         F.C.value('local-name(.)', 'nvarchar(128)') as IndicatorName,
         F.C.value('.', 'nvarchar(max)') as IndicatorValue
    from CTE1 as c
        outer apply c.Data.nodes('row/@*') as F(C)
)
select * from CTE2 where IndicatorName like 'Indicator%'

sql fiddle demo

আপনি ডায়নামিক এসকিউএলও লিখতে পারেন, তবে আমি এক্সএমএল আরও পছন্দ করি - ডায়নামিক এসকিউএল-এর জন্য আপনাকে টেবিল থেকে সরাসরি ডেটা নির্বাচন করার অনুমতি থাকতে হবে এবং এটি সর্বদা বিকল্প নয়।

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

কনস

  • এটি ডায়নামিক এসকিউএল হিসাবে তত দ্রুত নয় , রুক্ষ পরীক্ষাগুলি আমাকে দিয়েছে যে এক্সএমএল প্রায় গতিবেগের চেয়ে 2.5 গুণ কম গতিবেগ হয় (এটি 250000 ডলার সারণির টেবিলে একটি প্রশ্ন ছিল, সুতরাং এই অনুমানটি কোনওভাবেই সঠিক নয়)। আপনি চাইলে আপনি নিজের সাথে এটি তুলনা করতে পারেন, এখানে স্কিলফিল্ড উদাহরণস্বরূপ, 100000 সারিগুলিতে এটি 29 এস (এক্সএমএল) বনাম 14 এস (গতিশীল) ছিল;
  • এক্সপ্যাথের সাথে পরিচিত না লোকদের পক্ষে এটি বোঝা আরও কঠিন হতে পারে ;

অনুকূল

  • এটি আপনার অন্যান্য প্রশ্নের মতোই সুযোগ এবং এটি খুব সহজ হতে পারে। কয়েকটি উদাহরণ মাথায় আসে
    • আপনি আপনার ট্রিগার ভিতরে কোয়েরি insertedএবং deletedটেবিল (ডায়নামিক সঙ্গে মোটেই সম্ভব নয়) করতে পারে;
    • টেবিল থেকে সরাসরি নির্বাচনের ব্যবহারকারীর অনুমতি থাকতে হবে না । আমার অর্থ হ'ল যদি আপনার কাছে প্রক্রিয়া স্তর সংরক্ষণ করা থাকে এবং ব্যবহারকারীর এসপি চালানোর অনুমতি থাকে তবে টেবিলগুলি সরাসরি জিজ্ঞাসা করার অনুমতি না থাকলে আপনি এখনও এই জিজ্ঞাসাটি সঞ্চিত পদ্ধতিতে ব্যবহার করতে পারেন;
    • আপনি আপনার ক্ষেত্রের মধ্যে সারণী ভেরিয়েবলটি জিজ্ঞাসা করতে পারেন (ডায়নামিক এসকিউএল এর ভিতরে এটি পাস করার জন্য আপনাকে এটির পরিবর্তে অস্থায়ী টেবিল তৈরি করতে হবে বা টাইপ তৈরি করতে হবে এবং এটি গতিশীল এসকিউএল হিসাবে প্যারামিটার হিসাবে পাস করতে হবে;
  • আপনি এই ক্যোয়ারীটি ফাংশনের ভিতরে করতে পারেন (স্কেলার বা টেবিলের মূল্যবান)। ফাংশনগুলির মধ্যে ডায়নামিক এসকিউএল ব্যবহার করা সম্ভব নয়;

2
আপনি এক্সএমএল দিয়ে কোন ডেটা নির্বাচন করছেন যা টেবিল থেকে ডেটা নির্বাচন করার প্রয়োজন নেই?
অ্যারন বারট্রান্ড 21

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

3
আপনি যদি চান যে আপনার ব্যবহারকারীরা কোডটি কার্যকর করতে সক্ষম হন তবে কোডটি কার্যকর করার জন্য তাদের যেভাবে অ্যাক্সেসের প্রয়োজন তাদের আপনাকে দিতে হবে। আপনার উত্তরটি আরও ভাল করে দেওয়ার জন্য প্রয়োজনীয়তাগুলি তৈরি করবেন না (আপনার উত্তরটি দেখার জন্য আপনাকে প্রতিযোগিতামূলক উত্তরগুলি সম্পর্কেও মন্তব্য করতে হবে না - যদি তারা উত্তরটি খুঁজে পান তবে তারা আপনারও খুঁজে পেতে পারে)।
অ্যারন বারট্রান্ড 21

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

2
আমি বলব সময়কাল 10x পার্থক্য গুরুত্বপূর্ণ, হ্যাঁ। এবং ,000 8,000 সারিগুলি "বড় পরিমাণের ডেটা" নয় - 800,000 সারিগুলির বিপরীতে কি ঘটে দেখা উচিত?
অ্যারন বারট্রান্ড 22

7

কেবল নতুন পাঠকদের সহায়তা করার জন্য, আমি ইউএনপিভোট সম্পর্কে @ ব্লুফিটের উত্তরটি আরও ভালভাবে বুঝতে একটি উদাহরণ তৈরি করেছি।

 SELECT id
        ,entityId
        ,indicatorname
        ,indicatorvalue
  FROM (VALUES
        (1, 1, 'Value of Indicator 1 for entity 1', 'Value of Indicator 2 for entity 1', 'Value of Indicator 3 for entity 1'),
        (2, 1, 'Value of Indicator 1 for entity 2', 'Value of Indicator 2 for entity 2', 'Value of Indicator 3 for entity 2'),
        (3, 1, 'Value of Indicator 1 for entity 3', 'Value of Indicator 2 for entity 3', 'Value of Indicator 3 for entity 3'),
        (4, 2, 'Value of Indicator 1 for entity 4', 'Value of Indicator 2 for entity 4', 'Value of Indicator 3 for entity 4')
       ) AS Category(ID, EntityId, Indicator1, Indicator2, Indicator3)
UNPIVOT
(
    indicatorvalue
    FOR indicatorname IN (Indicator1, Indicator2, Indicator3)
) UNPIV;

3

মাইক্রোসফ্ট এসকিউএল সার্ভারে কলামগুলি সারিগুলিতে রূপান্তর করার জন্য আমার একটি সমাধানের প্রয়োজন ছিল, কলামের নামগুলি না জেনে (ট্রিগারে ব্যবহৃত) এবং গতিশীল এসকিএল ছাড়াই (গতিশীল এসকিউএল একটি ট্রিগারে ব্যবহারের জন্য খুব ধীর)।

অবশেষে আমি এই সমাধানটি পেয়েছি, যা ভাল কাজ করে:

SELECT
    insRowTbl.PK,
    insRowTbl.Username,
    attr.insRow.value('local-name(.)', 'nvarchar(128)') as FieldName,
    attr.insRow.value('.', 'nvarchar(max)') as FieldValue 
FROM ( Select      
          i.ID as PK,
          i.LastModifiedBy as Username,
          convert(xml, (select i.* for xml raw)) as insRowCol
       FROM inserted as i
     ) as insRowTbl
CROSS APPLY insRowTbl.insRowCol.nodes('/row/@*') as attr(insRow)

যেমন আপনি দেখতে পাচ্ছেন, আমি সারিটি এক্সএমএলে রূপান্তর করি (সাবকিউরি i, * xML কাঁচা জন্য নির্বাচন করুন, এটি সমস্ত কলামকে একটি এক্সএমএল কলামে রূপান্তর করে)

তারপরে আমি এই কলামটির প্রতিটি এক্সএমএল বৈশিষ্ট্যে ক্রিয়াকলাপটি ক্রস করি, যাতে আমি প্রতি গুণাবলীতে একটি সারি পাই।

সামগ্রিকভাবে, এটি কলামগুলির নামগুলি না জেনে এবং ডায়নামিক স্কোয়েল ব্যবহার না করে সারিগুলিকে সারিগুলিতে রূপান্তর করে। এটা আমার উদ্দেশ্যে যথেষ্ট দ্রুত।

(সম্পাদনা করুন: আমি উপরে রোমান পেকার উত্তরটি দেখেছি, যিনি একই কাজ করছেন I গতিশীল স্কয়ার, যাইহোক, এই সমাধানটি খুব সাধারণ একটি সর্বজনীন, সুতরাং এটির অবশ্যই একটি বিকল্প)।

আমি এই জায়গায় এই মন্তব্যটি রেখে চলেছি, কারণ আমি সম্পূর্ণ নিরীক্ষার ট্রিগার সম্পর্কে আমার পোস্টে এই ব্যাখ্যাটি উল্লেখ করতে চাই, যা আপনি এখানে পেতে পারেন: https://stackoverflow.com/a/43800286/4160788


3
DECLARE @TableName varchar(max)=NULL
SELECT @TableName=COALESCE(@TableName+',','')+t.TABLE_CATALOG+'.'+ t.TABLE_SCHEMA+'.'+o.Name
  FROM sysindexes AS i
  INNER JOIN sysobjects AS o ON i.id = o.id
  INNER JOIN INFORMATION_SCHEMA.TABLES T ON T.TABLE_NAME=o.name
 WHERE i.indid < 2
  AND OBJECTPROPERTY(o.id,'IsMSShipped') = 0
  AND i.rowcnt >350
  AND o.xtype !='TF'
 ORDER BY o.name ASC

 print @tablename

আপনি সারণীগুলির তালিকা পেতে পারেন যা সারি> অ্যাকাউন্টস 350> রয়েছে। সারি হিসাবে সারণির সমাধান তালিকায় দেখতে পাবেন।


2

আমি এটি উল্লেখ না করেই দেখেছি।

যদি 2016+ হয় তবে ডায়নামিক এসকিউএল না ব্যবহার করে ডায়নামিকভাবে ডেটা আনপিবট করার আরও একটি বিকল্প এখানে।

উদাহরণ

Declare @YourTable Table ([ID] varchar(50),[Col1] varchar(50),[Col2] varchar(50))
Insert Into @YourTable Values 
 (1,'A','B')
,(2,'R','C')
,(3,'X','D')

Select A.[ID]
      ,Item  = B.[Key]
      ,Value = B.[Value]
 From  @YourTable A
 Cross Apply ( Select * 
                From  OpenJson((Select A.* For JSON Path,Without_Array_Wrapper )) 
                Where [Key] not in ('ID','Other','Columns','ToExclude')
             ) B

রিটার্নস

ID  Item    Value
1   Col1    A
1   Col2    B
2   Col1    R
2   Col2    C
3   Col1    X
3   Col2    D
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.