একাধিক কলামে পিভট সারি


21

আমার একটি এসকিউএল সার্ভার উদাহরণ রয়েছে যা ওরাকল সার্ভারের সাথে লিঙ্কযুক্ত সার্ভার রয়েছে। ওরাকল সার্ভারে একটি টেবিল PersonOptionsরয়েছে যার নাম রয়েছে:

╔══════════╦══════════╗
║ PersonID ║ OptionID ║
╠══════════╬══════════╣
║        1 ║ A        ║
║        1 ║ B        ║
║        2 ║ C        ║
║        3 ║ B        ║
║        4 ║ A        ║
║        4 ║ C        ║
╚══════════╩══════════╝

আমার সেই ডেটাটি পিভট করা দরকার যাতে ফলাফলগুলি হয়:

╔══════════╦═════════╦══════════╦══════════╗
║ PersonID ║ OptionA ║ Option B ║ Option C ║
╠══════════╬═════════╬══════════╬══════════╣
║        1 ║       1 ║        1 ║          ║
║        2 ║         ║          ║        1 ║
║        3 ║         ║        1 ║          ║
║        4 ║       1 ║          ║        1 ║
╚══════════╩═════════╩══════════╩══════════╝

কোন পরামর্শ?

উত্তর:


20

কয়েকটি উপায়ে আপনি এই ডেটা ট্রান্সফর্মেশনটি সম্পাদন করতে পারেন। আপনার PIVOTফাংশনে অ্যাক্সেস রয়েছে তবে এটি সবচেয়ে সহজ হবে, তবে তা না হলে আপনি একটি সামগ্রিক ফাংশন এবং এ ব্যবহার করতে পারেন CASE

সমষ্টি / কেস সংস্করণ:

select personid,
  max(case when optionid = 'A' then 1 else 0 end) OptionA,
  max(case when optionid = 'B' then 1 else 0 end) OptionB,
  max(case when optionid = 'C' then 1 else 0 end) OptionC
from PersonOptions
group by personid
order by personid;

ডেমো সহ এসকিউএল ফিডল দেখুন

স্ট্যাটিক পাইভট:

select *
from
(
  select personid, optionid
  from PersonOptions
) src
pivot
(
  count(optionid)
  for optionid in ('A' as OptionA, 'B' OptionB, 'C' OptionC)
) piv
order by personid

ডেমো সহ এসকিউএল ফিডল দেখুন

গতিশীল সংস্করণ:

উপরের দুটি সংস্করণ দুর্দান্ত কাজ করে যদি আপনার পরিচিত সংখ্যার মান থাকে তবে আপনার মানগুলি যদি অজানা থাকে তবে আপনি গতিশীল এসকিএল বাস্তবায়ন করতে চান এবং ওরাকলে আপনি একটি পদ্ধতি ব্যবহার করতে পারেন:

CREATE OR REPLACE procedure dynamic_pivot_po(p_cursor in out sys_refcursor)
as
    sql_query varchar2(1000) := 'select personid ';

    begin
        for x in (select distinct OptionID from PersonOptions order by 1)
        loop
            sql_query := sql_query ||
                ' , min(case when OptionID = '''||x.OptionID||''' then 1 else null end) as Option_'||x.OptionID;

                dbms_output.put_line(sql_query);
        end loop;

        sql_query := sql_query || ' from PersonOptions group by personid order by personid';
        dbms_output.put_line(sql_query);

        open p_cursor for sql_query;
    end;
/

তারপরে আপনি ফলাফলগুলি ফেরত দিন, আপনি ব্যবহার করবেন:

variable x refcursor
exec dynamic_pivot_po(:x)
print x

ফলাফলগুলি সমস্ত সংস্করণের সাথে এক রকম:

| PERSONID | OPTIONA | OPTIONB | OPTIONC |
------------------------------------------
|        1 |       1 |       1 |       0 |
|        2 |       0 |       0 |       1 |
|        3 |       0 |       1 |       0 |
|        4 |       1 |       0 |       1 |

তবে স্ট্যাটিক পিভট সলিউশন ধরে নিচ্ছে কেবল তিনটি বিকল্প রয়েছে are আপনার যদি সম্ভাব্য সীমাহীন সংখ্যক বিকল্প থাকে? উদাহরণস্বরূপ এবিসিডিডিএফজিআইজিকে? নিয়মিত স্কুএল দিয়ে পিভটকে গতিশীল করার কোনও উপায় নেই? বিকল্পগুলি কলামের শিরোনাম তৈরির পরিবর্তে, আমরা কি কেবল তাদের কলামগুলিতে রেখে দিতে পারি? সুতরাং এটি দেখতে এই মত হবে: | ব্যক্তিগত | কলাম 2 | কলাম 3 | কলাম 4 | ------------------------------------------ | 1 | ক | বি | নাল | | 2 | সি | নাল | নাল | | 3 | নাল | সি | নাল |
ম্যাথু

1
@ ম্যাথহে আপনি উত্তরের শেষ অংশে প্রদর্শিত হিসাবে ডায়নামিক স্কেল ব্যবহার করতে চাইবেন।
Taryn

দ্রুত সাড়া দেওয়ার জন্য ধন্যবাদ! আমি আসলে এটি একটি নতুন কলাম তৈরি করে এবং সেখানে কমা দ্বারা পৃথক সমস্ত বিকল্প স্টাফ করে ing একই টেবিল থেকে নির্বাচন করণ একটি subquery থেকে উত্পন্ন where a.personId = a2.personId order by a2.personId for xml path('')। a2 সাবকোয়ারির টেবিল। তারপরে আমি ডেলিমিটার হিসাবে কমাতে কলামে পাঠ্য ব্যবহার করে এক্সেলে ডেটা আলাদা করি। আমি কোনও পদ্ধতি লিখতে না পেরে নিয়মিত এসকিএল-তে এটি করার উপায় খুঁজে পাওয়ার আশা করছিলাম, তবে সম্ভবত কোনও উপায় নেই। এই মুহুর্তে দৌড়াতে হবে তবে আরও ভাল করে ব্যাখ্যা করার জন্য আমি এর একটি উদাহরণ পোস্ট করার চেষ্টা করব।
ম্যাথু

9

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

WITH PersonOptions(PersonID, OptionId) AS
(
    SELECT 1, 'A'
    UNION ALL SELECT 1, 'B'
    UNION ALL SELECT 2, 'C'
    UNION ALL SELECT 3, 'B'
    UNION ALL SELECT 4, 'A'
    UNION ALL SELECT 4, 'C'
)
SELECT
    P.PersonId
,   NULLIF(P.A, 0) AS OptionA
,   NULLIF(P.B, 0) AS OptionB
,   NULLIF(P.C, 0) AS OptionC
FROM
    PersonOptions  PO
    PIVOT 
    (
        COUNT(PO.OptionId)
        FOR OPtionId IN (A, B, C)
    )  P;

5

আমি ম্যানুয়ালি পিভট ক্যোয়ারী পছন্দ করি তবে আপনি এটিও ব্যবহার করতে পারেন PIVOT

SELECT PersonID,
MAX(CASE WHEN OptionId ='A' THEN 1 END) AS OptionA,
MAX(CASE WHEN OptionId ='B' THEN 1 END) AS OptionB, 
MAX(CASE WHEN OptionId ='C' THEN 1 END) AS OptionC
FROM PersonOptions
GROUP BY PersonID

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

2
@ জকোলেব্রান্ড: এটি ব্যক্তিগত পছন্দ সম্পর্কে আরও বেশি - আমি নিজেই মনে করি যে PIVOTআমার ব্যবহারের পদ্ধতির তুলনায় বাক্য গঠন আরও সংশ্লেষিত । তবে, আমি সচেতন উভয়ই একই ফল দেয় এবং আমি সম্মত হই যে অন্য লোকেরা এর বিপরীতে ভাবতে পারে।
a1ex07

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