স্ব যোগদানের বিকল্প


10

আমি এখানে একটি প্রশ্ন জিজ্ঞাসা করেছি: /programming/43807566/how-to-divide-two-values-from-tame-same-column-but-at-differences-rows

একই টেবিল থেকে একই কলামে তবে বিভিন্ন সারিতে মানগুলি ভাগ করার বিষয়ে। এখন আমার সমস্যা আছে যেখানে আমার আরও বেশি সংখ্যক এবং ডিনোমিনেটর রয়েছে (ভিন্ন ভিন্ন uns)। self joinপোস্টগ্রিসের সাহায্যে এই সমস্যাটি সমাধান করার এখনও কি ভাল উপায় বা আরও ভাল সমাধান রয়েছে?

উদাহরণ:

| postcode | value | uns |
|----------|-------|-----|
|       AA |    40 |  53 |
|       BB |    20 |  53 |
|       AA |    10 |  54 |
|       AA |    20 |  55 |
|       AA |    10 |  56 |
|       AA |    30 |  57 |
|       AA |    50 |  58 |
|       BB |    10 |  54 |
|       BB |    10 |  55 |
|       BB |    70 |  56 |
|       BB |    80 |  57 |
|       BB |    10 |  58 |

ফলাফল হওয়া উচিত:

| postcode | formula    |
|----------|------------|
|       AA | 18.888...  |
|       BB | 14.375     |

যেখানে মানটি পোস্টকোড দ্বারা শ্রেণিবদ্ধ করা হয় এবং সূত্রটি (আনসন সহ মান):

(V53 * V56 + V54 * V57 + V55 * V58) / (V56 + V57 + V58)

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


আপনার টেবিলের এমন কোনও ক্ষেত্র রয়েছে যা পতাকাটি সারি সারি সংখ্যা এবং ডিনোমিনেটর?
ম্যাকনেটস

না, হর UNS 56, 57, 58. সঙ্গে মূল্যবোধের সমষ্টি
এলোমেলো

সেরা সমাধানের মতো শব্দগুলি unsহ'ল ডেভেল পিভট করা যাতে কলামের নাম হয়ে যায় - সেখান থেকে, যে কোনও সূত্র মান ব্যবহার করে তা কার্যক্ষম হয়ে ওঠে। সূত্রটি কি হার্ড-কোডেড, বা গতিশীলভাবে কোনওভাবে উত্পন্ন হবে?
আরডিফোজ

কয়েক সূত্র (~ 30) যার অনেকগুলি টেবিল তৈরি করতে লাগবে আছে
এলোমেলো

উত্তর:


3

এটি মাইকেল যেমন ইতিমধ্যে নিখুঁতভাবে নির্ণয় করা হয়েছে এর মূল ভিত্তিতে একটি পাইভট / ক্রসস্ট্যাব সমস্যা ।

আপনি যদি tablefuncপোস্টগ্র্রেসের মডিউলটির সাথে পরিচিত না হন তবে এখানে প্রাথমিক নির্দেশাবলী পড়ুন:

ক্যোয়ারীটি সহজ এবং খুব দ্রুত হয়ে ওঠে (এখানে উপস্থাপিত অন্যান্য সমাধানের চেয়ে দ্রুত):

SELECT (v53 * v56 + v54 * v57 + v55 * v58) / NULLIF(v56 + v57 + v58, 0)
FROM   crosstab(
   'SELECT postcode, uns, value FROM tbl ORDER BY 1'
 , 'SELECT generate_series(53,58)'
   ) AS ct (postcode text
          , v53 numeric, v54 numeric, v55 numeric
          , v56 numeric, v57 numeric, v58 numeric);

NULLIF শূন্য দ্বারা বিভাগ রোধ করতে।

এখানে ডিবিফিডল


6

আপনি সমস্ত আনস / মান জোড়াকে একটি জেএসওএন অবজেক্টে একত্রিত করতে পারেন, তারপরে নামটি দিয়ে ইউএনএস মানগুলি অ্যাক্সেস করতে এটি ব্যবহার করুন। এর জন্য কিছু কাস্টিং প্রয়োজন কারণ মানগুলি কেবল JSON অবজেক্ট থেকে পাঠ্য হিসাবে বের করা যেতে পারে, তবে সূত্রটি আপনার বর্ণনার সাথে একই রকম দেখায়:

with vals(postcode, v) as (
  select postcode, json_object_agg(uns, value)
  from x
  group by postcode
), factors (postcode, denominator, divisor) as (
  select postcode, 
         (v->>'53')::decimal * (v->>'56')::decimal + (v->>'54')::decimal * (v->>'57')::decimal + (v->>'55')::decimal * (v->>'58')::decimal,
         (v->>'56')::decimal + (v->>'57')::decimal + (v->>'58')::decimal
  from vals
)
select postcode, 
       denominator / nullif(divisor, 0)
from factors;

এগ্রিগেশন, ডিনোমিনেটর এবং বিভাজকের মূল্যায়ন এবং চূড়ান্ত বিভাগটিকে আরও পঠনযোগ্য করার জন্য তিনটি ধাপে বিভক্ত করেছি।

অনলাইন উদাহরণ: http://rextester.com/IZYT54566


আপনি একটি ফাংশন তৈরি করে সূত্রটি সহজ করতে পারেন:

create function val(p_vals json, p_uns text)
  returns decimal
as $$
  select (p_vals ->> p_uns)::decimal;
$$
language sql;

with vals (postcode, v) as (
  select postcode, json_object_agg(uns, value)
  from x
  group by postcode
), factors (postcode, denominator, divisor) as (
  select postcode, 
         val(v, '53') * val(v, '56') + val(v, '54') * val(v, '57') + val(v, '55') * val(v, '58'),
         val(v, '56') + val(v, '57') + val(v, '58')
  from vals
)
select postcode, 
       denominator / nullif(divisor, 0)
from factors;

4

পিভট প্যাটার্ন এটির জন্য কাজ করবে। এটি সারিগুলির মানগুলি তাদের সাধারণ কী অনুসারে একক সারিতে কলামগুলিতে রূপান্তর করে। একটা হয় কয়েকটি উপায় এই বাস্তবায়ন। কারও কারও কাছে কেবল একটি একক টেবিল স্ক্যান প্রয়োজন।

PIVOT এর পরে আপনার কাছে পোস্টকোডের জন্য এক সারি এবং মান অনুসারে একটি কলাম থাকবে। ক্যোয়ারির অবশিষ্ট অংশগুলি এমনভাবে লেখা হবে যেমন এটি একটি একক সারণীর রেফারেন্স করেছে।


3

Assuming যে (postcode, uns)হয় UNIQUE(সম্ভবত, একটি পি কে), পিভট প্যাটার্ন, যেমন ইতিমধ্যে @ মাইকেল-সবুজ দ্বারা মন্তব্য, প্রয়োগ করা যাবে portably নিম্নলিখিত ক্যোয়ারী ব্যবহার করে:

SELECT
     postcode, 
     CAST(V53 * V56 + V54 * V57 + V55 * V58 AS numeric) 
         / nullif(V56 + V57 + V58, 0) AS formula
FROM
    (SELECT
         postcode,
         sum(case when uns=53 then value end) AS v53,     
         sum(case when uns=54 then value end) AS v54,     
         sum(case when uns=55 then value end) AS v55,     
         sum(case when uns=56 then value end) AS v56,
         sum(case when uns=57 then value end) AS v57,
         sum(case when uns=58 then value end) AS v58
    FROM
         t
    GROUP BY
         postcode
    ) AS s
ORDER BY
    postcode ;

এটি এসকিউএলফিডেলে দেখুন


3

Assuming যে (postcode, uns)হয় UNIQUE(সম্ভবত, একটি পি কে), সম্ভবত সবচেয়ে সহজ : পথ, সম্ভবত সবচেয়ে পোর্টেবল এক, যদিও সম্ভবত অনুকূল না হিসাবে প্রয়োজন অনেক subselects হিসাবে ব্যবহারের :

SELECT
    postcode,
    ((SELECT value FROM t WHERE t.uns = 53 AND t.postcode = p.postcode) *
     (SELECT value FROM t WHERE t.uns = 56 AND t.postcode = p.postcode) +
     (SELECT value FROM t WHERE t.uns = 54 AND t.postcode = p.postcode) *
     (SELECT value FROM t WHERE t.uns = 57 AND t.postcode = p.postcode) +
     (SELECT value FROM t WHERE t.uns = 55 AND t.postcode = p.postcode) *
     (SELECT value FROM t WHERE t.uns = 58 AND t.postcode = p.postcode)
    )::double precision / 
     nullif( (SELECT sum(value) FROM t 
              WHERE t.uns IN (56, 57, 58) AND t.postcode = p.postcode), 0)
    AS formula
FROM
    (SELECT DISTINCT postcode FROM t) AS p
ORDER BY
    postcode ;

এসকিউএলফিডেলে চেক করুন ।

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