ফলস্বরূপ টেবিল সংজ্ঞাটি অজানা যেখানে আমি কীভাবে একটি পাইভোটড ক্রস যোগ দিতে পারি?


18

একটি নাম এবং মান সহ একটি অপরিশোধিত সারির গণনা সহ দুটি সারণী দেওয়া হয়েছে , কীভাবে আমি CROSS JOINতাদের মানগুলির উপরে কোনও ক্রিয়াকলাপ প্রদর্শন করব ।

CREATE TEMP TABLE foo AS
SELECT x::text AS name, x::int
FROM generate_series(1,10) AS t(x);

CREATE TEMP TABLE bar AS
SELECT x::text AS name, x::int
FROM generate_series(1,5) AS t(x);

উদাহরণস্বরূপ, যদি সেই ফাংশনটি গুণক হয় তবে আমি কীভাবে নীচের মতো একটি (গুণ) টেবিল তৈরি করব,

১.১২ এর সাধারণ গুণন সারণী

এই সমস্ত (arg1,arg2,result)সারি দিয়ে তৈরি করা যায়

SELECT foo.name AS arg1, bar.name AS arg2, foo.x*bar.x AS result
FROM foo
CROSS JOIN bar; 

সুতরাং এটি কেবল উপস্থাপনের প্রশ্ন, আমি এটি একটি কাস্টম নামের সাথেও কাজ করতে চাই - এমন একটি নাম যা কেবল CASTপাঠ্যে আর্গুমেন্ট নয় কেবল সারণীতে সেট করা হয়,

CREATE TEMP TABLE foo AS
SELECT chr(x+64) AS name, x::int
FROM generate_series(1,10) AS t(x);

CREATE TEMP TABLE bar AS
SELECT chr(x+72) AS name, x::int
FROM generate_series(1,5) AS t(x);

আমি মনে করি এটি একটি গতিশীল রিটার্ন-টাইপের সক্ষম ক্রসস্ট্যাব দিয়ে সহজেই সক্ষম হবে।

SELECT * FROM crosstab(
  '
    SELECT foo.x AS arg1, bar.x AS arg2, foo.x*bar.x
    FROM foo
    CROSS JOIN bar
  ', 'SELECT DISTINCT name FROM bar'
) AS **MAGIC**

কিন্তু, ছাড়া **MAGIC** , আমি পেতে

ERROR:  a column definition list is required for functions returning "record"
LINE 1: SELECT * FROM crosstab(

রেফারেন্সের জন্য, উপরোক্ত উদাহরণগুলি নামের সাথে ব্যবহার করা এর মতো আরও কিছু tablefunc 'র crosstab()চায়।

SELECT * FROM crosstab(
  '
    SELECT foo.x AS arg1, bar.x AS arg2, foo.x*bar.x
    FROM foo
    CROSS JOIN bar
  '
) AS t(row int, i int, j int, k int, l int, m int);

তবে, এখন আমরা barআমাদের উদাহরণে টেবিলের সামগ্রী এবং আকার সম্পর্কে অনুমান করাতে ফিরে এসেছি । তাই যদি,

  1. সারণীগুলি নির্ধারিত দৈর্ঘ্যের হয়,
  2. তারপরে ক্রস-যোগটি অপরিজ্ঞাত মাত্রার ঘনককে উপস্থাপন করে (উপরের কারণে),
  3. ক্যাটাগরি-নামগুলি (ক্রস-ট্যাব পার্লেন্স) সারণীতে রয়েছে

এই জাতীয় উপস্থাপনা তৈরি করতে "কলাম সংজ্ঞা তালিকা" ছাড়াই পোস্টগ্র্রেএসকিউএল-এ আমরা কী করতে পারি?


1
JSON ফলাফল কি একটি ভাল পদ্ধতির হতে পারে? একটি অ্যারে কি ভাল অ্যাপ্রপোচ হতে পারে? এইভাবে, "আউটপুট টেবিল" এর সংজ্ঞাটি ইতিমধ্যে জানা যাবে (এবং স্থির)। আপনি নমনীয়তাটি JSON বা ARRAY এর মধ্যে রেখেছেন। আমি অনুমান করি যে তথ্যটি প্রক্রিয়া করার জন্য এটি পরে ব্যবহৃত অনেকগুলি সরঞ্জাম নির্ভর করবে।
jananolo

আমি যদি এটি সম্ভব হয় তবে উপরের মতো ঠিক পছন্দ করবো।
ইভান ক্যারল

উত্তর:


12

সাধারণ কেস, স্ট্যাটিক এসকিউএল

অ গতিশীল সঙ্গে সমাধান crosstab()সহজ ক্ষেত্রে জন্য:

SELECT * FROM crosstab(
  'SELECT b.x, f.name, f.x * b.x AS prod
   FROM   foo f, bar b
   ORDER  BY 1, 2'
   ) AS ct (x int, "A" int, "B" int, "C" int, "D" int, "E" int
                 , "F" int, "G" int, "H" int, "I" int, "J" int);

আমি ফলস্বরূপ কলামগুলি আদেশ করি foo.name, নয় foo.x। উভয় সমান্তরালে বাছাই করা ঘটেছে, কিন্তু এটি কেবল সহজ সেটআপ। আপনার ক্ষেত্রে সঠিক ক্রম অর্ডার চয়ন করুন। দ্বিতীয় কলামের আসল মান এই প্রশ্নের সাথে অপ্রাসঙ্গিক (1-প্যারামিটার ফর্ম crosstab())।

আমাদের এমনকি crosstab()2 টি প্যারামিটারের প্রয়োজন নেই কারণ সংজ্ঞা অনুসারে কোনও অনুপস্থিত মান নেই। দেখা:

(আপনি পরবর্তী সম্পাদনাতে প্রতিস্থাপনের fooমাধ্যমে প্রশ্নের ক্রসস্ট্যাব ক্যোয়ারীটি ঠিক করেছেন barThis এটি কোয়েরিটিও ঠিক করে দেয় তবে নাম থেকে কাজ করে চলেছে foo))

অজানা ফেরতের প্রকার, গতিশীল এসকিউএল

কলামের নাম এবং প্রকারগুলি গতিশীল হতে পারে না। এসকিউএল কল সময়ে নাম্বার, নাম এবং ফলাফল কলামগুলির প্রকারগুলি জানতে চায়। হয় সুস্পষ্ট ঘোষণার মাধ্যমে বা সিস্টেম ক্যাটালগগুলির তথ্য থেকে (যা ঘটে তা-ও ঘটেSELECT * FROM tbl : পোস্টগ্রিস নিবন্ধিত সারণির সংজ্ঞাটি দেখায়))

আপনি চাইছেন যে পোস্টগ্রিজ কোনও ব্যবহারকারীর সারণীতে ডেটা থেকে ফলাফল কলামগুলি পেতে পারে umns ঘটতে যাচ্ছে না.

এক উপায় বা অন্য কোনওভাবে আপনার সার্ভারে দুটি রাউন্ড ট্রিপ দরকার । হয় আপনি একটি কার্সার তৈরি করেন এবং তারপরেই হাঁটুন। অথবা আপনি একটি টেম্প টেবিল তৈরি করেন এবং তারপরে এটি নির্বাচন করুন। অথবা আপনি কোনও প্রকার নিবন্ধন করুন এবং এটি কলটিতে ব্যবহার করুন।

অথবা আপনি কেবল একটি পদক্ষেপে ক্যোয়ারী তৈরি করেন এবং এটি পরবর্তী সময়ে কার্যকর করুন:

SELECT $$SELECT * FROM crosstab(
  'SELECT b.x, f.name, f.x * b.x AS prod
   FROM   foo f, bar b
   ORDER  BY 1, 2'
   ) AS ct (x int, $$
 || string_agg(quote_ident(name), ' int, ' ORDER BY name) || ' int)'
FROM   foo;

এটি গতিশীলভাবে উপরের প্রশ্নটি উত্পন্ন করে। পরবর্তী পদক্ষেপে এটি কার্যকর করুন।

$$নেস্টেড কোটগুলি হ্যান্ডলিংটি সহজ রাখতে আমি ডলার-কোট ( ) ব্যবহার করছি । দেখা:

quote_ident() অন্যথায় অবৈধ কলামের নামগুলি (এবং সম্ভবত এসকিউএল ইঞ্জেকশনের বিরুদ্ধে প্রতিরক্ষা করা) এড়াতে প্রয়োজনীয়।

সম্পর্কিত:


আমি লক্ষ্য করেছি যে আপনি "অজানা রিটার্ন টাইপ, ডায়নামিক এসকিউএল" বলেছিলেন এমন কোয়েরিটি সম্পাদন করে আসলে একটি স্ট্রিং দেয় যা অন্য কোয়েরিকে উপস্থাপন করে এবং তারপরে আপনি "পরের ধাপে এটি কার্যকর করুন" বলে থাকেন। এর অর্থ কি এর অর্থ এই যে, উদাহরণস্বরূপ এটিকে বাদ দিয়ে কোনও বস্তুগত দৃষ্টিভঙ্গি তৈরি করা কঠিন হবে?
কলিন ডি

@ কলিনডি: কঠিন নয়, তবে সহজ অসম্ভব। আপনি জেনারেট এসকিউএল থেকে পরিচিত রিটার্ন টাইপ সহ একটি এমভি তৈরি করতে পারেন। তবে অজানা রিটার্নের ধরণ সহ আপনার এমভি থাকতে পারে না।
এরউইন ব্র্যান্ডসেটেটার

11

এই জাতীয় উপস্থাপনা তৈরি করতে "কলাম সংজ্ঞা তালিকা" ছাড়াই পোস্টগ্র্রেএসকিউএল-এ আমরা কী করতে পারি?

আপনি যদি এটি উপস্থাপনা সমস্যা হিসাবে ফ্রেম করেন তবে আপনি পোস্ট-কোয়েরি উপস্থাপনা বৈশিষ্ট্যটি বিবেচনা করতে পারেন।

psql(৯..6) এর নতুন সংস্করণগুলি \crosstabviewএসকিউএল সমর্থন ছাড়াই ক্রসস্ট্যাব উপস্থাপনার ফলাফল দেখায় (যেহেতু এসকিউএল এটি সরাসরি উত্পাদন করতে পারে না, @ এরউইনের উত্তরে উল্লিখিত হয়েছে: এসকিউএল কল টাইমে ফলাফল, কলামগুলির সংখ্যা, নাম জানতে চায়) )

উদাহরণস্বরূপ, আপনার প্রথম ক্যোয়ারী দেয়:

SELECT foo.name AS arg1, bar.name AS arg2, foo.x*bar.x AS result
FROM foo
CROSS JOIN bar
\crosstabview

 arg1 | 1  | 2  | 3  | 4  | 5  
------+----+----+----+----+----
 1    |  1 |  2 |  3 |  4 |  5
 2    |  2 |  4 |  6 |  8 | 10
 3    |  3 |  6 |  9 | 12 | 15
 4    |  4 |  8 | 12 | 16 | 20
 5    |  5 | 10 | 15 | 20 | 25
 6    |  6 | 12 | 18 | 24 | 30
 7    |  7 | 14 | 21 | 28 | 35
 8    |  8 | 16 | 24 | 32 | 40
 9    |  9 | 18 | 27 | 36 | 45
 10   | 10 | 20 | 30 | 40 | 50
(10 rows)

ASCII কলামের নাম সহ দ্বিতীয় উদাহরণ দেয়:

SELECT foo.name AS arg1, bar.name AS arg2, foo.x*bar.x
    FROM foo
    CROSS JOIN bar
  \crosstabview

 arg1 | I  | J  | K  | L  | M  
------+----+----+----+----+----
 A    |  1 |  2 |  3 |  4 |  5
 B    |  2 |  4 |  6 |  8 | 10
 C    |  3 |  6 |  9 | 12 | 15
 D    |  4 |  8 | 12 | 16 | 20
 E    |  5 | 10 | 15 | 20 | 25
 F    |  6 | 12 | 18 | 24 | 30
 G    |  7 | 14 | 21 | 28 | 35
 H    |  8 | 16 | 24 | 32 | 40
 I    |  9 | 18 | 27 | 36 | 45
 J    | 10 | 20 | 30 | 40 | 50
(10 rows)

আরও কিছুর জন্য পিএসএইচএল ম্যানুয়াল এবং https://wiki.postgresql.org/wiki/Crosstabview দেখুন।


1
এটি আসলেই দুর্দান্ত।
ইভান ক্যারল

1
সবচেয়ে মার্জিত কাজ।
এরউইন ব্র্যান্ডসটেটার

1

এটি একটি নির্দিষ্ট সমাধান নয়

এটি এখন পর্যন্ত আমার সেরা পন্থা। এখনও চূড়ান্ত অ্যারে কলামে রূপান্তর করা প্রয়োজন।

প্রথমে আমি দুটি টেবিলের কার্টেসিয়ান পণ্য পেয়েছি:

select foo.name xname, bar.name yname, (foo.x * bar.x)::text as val,
       ((row_number() over ()) - 1) / (select count(*)::integer from foo) as row
 from bar
     cross join foo
 order by bar.name, foo.name

তবে, আমি প্রথম সারণির প্রতিটি সারি সনাক্ত করতে একটি সারি সংখ্যা যুক্ত করেছি।

((row_number() over ()) - 1) / (select count(*)::integer from foo)

তারপরে আমি ফলাফলটি এই বিন্যাসে বাইট করেছি:

[Row name] [Array of values]


select col_name, values
from
(
select '' as col_name, array_agg(name) as values from foo
UNION
select fy.name as col_name,
    (select array_agg(t.val) as values
    from  
        (select foo.name xname, bar.name yname, (foo.x * bar.x)::text as val,
              ((row_number() over ()) - 1) / (select count(*)::integer from foo) as row
        from bar
           cross join foo
        order by bar.name, foo.name) t
    where t.row = fy.row)
from
    (select name, (row_number() over(order by name)) - 1 as row from bar) fy
) a
order by col_name;

+---+---------------------+
|   |      ABCDEFGHIJ     |
+---+---------------------+
| I |     12345678910     |
+---+---------------------+
| J |   2468101214161820  |
+---+---------------------+
| K |  36912151821242730  |
+---+---------------------+
| L |  481216202428323640 |
+---+---------------------+
| M | 5101520253035404550 |
+---+---------------------+ 

এটিকে কোমা দ্বারা সীমাবদ্ধ স্ট্রিংয়ে রূপান্তর করা:

select col_name, values
from
(
select '' as col_name, array_to_string(array_agg(name),',') as values from foo
UNION
select fy.name as col_name,
    (select array_to_string(array_agg(t.val),',') as values
    from  
        (select foo.name xname, bar.name yname, (foo.x * bar.x)::text as val,
              ((row_number() over ()) - 1) / (select count(*)::integer from foo) as row
        from bar
           cross join foo
        order by bar.name, foo.name) t
    where t.row = fy.row)
from
    (select name, (row_number() over(order by name)) - 1 as row from bar) fy
) a
order by col_name;


+---+------------------------------+
|   | A,B,C,D,E,F,G,H,I,J          |
+---+------------------------------+
| I | 1,2,3,4,5,6,7,8,9,10         |
+---+------------------------------+
| J | 2,4,6,8,10,12,14,16,18,20    |
+---+------------------------------+
| K | 3,6,9,12,15,18,21,24,27,30   |
+---+------------------------------+
| L | 4,8,12,16,20,24,28,32,36,40  |
+---+------------------------------+
| M | 5,10,15,20,25,30,35,40,45,50 |
+---+------------------------------+

(এটি পরে চেষ্টা করার জন্য: http://rextester.com/NBCYXA2183 )


0

পার্শ্ব নোট হিসাবে, এটি এসকিউএল: ২০১ like এর মতো মনে হচ্ছে এটি বহুবর্ষীয় টেবিল ফাংশনগুলির সাথে সমন্বিত করবে (আইএসও / আইইসি টিআর 19075-7: 2017)

আমি এসকিউএল-এ হোয়াট নিউ: ২০১ the লিঙ্কটি পেয়েছি তবে লেখক এর বেশি প্রসারিত করে না।

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