পোস্টগ্রেরএসকিউএল-এ ল্যাটারাল এবং সাবকোয়ারির মধ্যে পার্থক্য কী?


146

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

আমি বুঝতে পারি যে LATERALযোগদান হতে পারে আমাকে সাহায্য করতে সক্ষম হতে পারে তবে হ্যাপ অ্যানালিটিক্সের মতো এই নিবন্ধগুলি পড়ার পরেও আমি এখনও বেশিরভাগ অনুসরণ করি না।

LATERALযোগদানের জন্য ব্যবহারের ক্ষেত্রে কী ? একটি LATERALযোগদান এবং subquery মধ্যে পার্থক্য কি ?


2
blog.heapanalytics.com/... এবং explainextended.com/2009/07/16/inner-join-vs-cross-apply (এসকিউএল সার্ভারের applyহিসাবে একই lateralএসকিউএল মান থেকে)
a_horse_with_no_name

উত্তর:


163

আরও একটি সম্পর্কিত সম্পর্কযুক্ত subquery মত

একটি LATERALযোগদান (9.3 বা পরবর্তী পোস্টগ্রেস ) আরও একটি সম্পর্কিত সম্পর্কযুক্ত সাবকোয়ারির মতো , কোনও সরল সাবকোয়ারির মতো নয়। অ্যান্ডোমার যেমন উল্লেখ করেছে , একটি LATERALযোগদানের ডানদিকে একটি ক্রিয়া বা subquery এর প্রতিটি বামের জন্য একবারের সাথে একবার- সম্পর্কিত subquery- যেমন একটি সরল subquery (টেবিল এক্সপ্রেশন) একবার মূল্যায়ন করা হয় একবার মূল্যায়ন করতে হবে । (ক্যোয়ারী পরিকল্পনাকারীর
উভয়ের পক্ষে পারফরম্যান্স অনুকূল করার উপায় রয়েছে)) এই সম্পর্কিত উত্তরের একই সমস্যা সমাধানের জন্য উভয় পক্ষে কোডের উদাহরণ রয়েছে:

একাধিক কলাম ফেরত LATERALদেওয়ার জন্য , একটি যোগদান সাধারণত সাধারণত সহজ, পরিষ্কার এবং দ্রুত হয়।
এছাড়াও, মনে রাখবেন যে একটি সম্পর্কযুক্ত সাবকোয়ারির সমতুল্য হ'ল LEFT JOIN LATERAL ... ON true:

ম্যানুয়াল চালু করুন LATERAL

আমরা এখানে উত্তর দিতে যাব তার চেয়ে এটি বেশি প্রামাণিক:

সাবকিউরিটি যে কাজগুলি করতে পারে না

সেখানে হয় যে একটি LATERALযোগদানের করতে পারেন, কিন্তু একটি (সম্পর্কিত) subquery (সহজে) করতে পারেন না। একটি সম্পর্কযুক্ত সাবকোয়ারি কেবল একটি একক মান প্রদান করতে পারে, একাধিক কলাম নয় এবং একাধিক সারি নয় - খালি ফাংশন কলগুলি ব্যতীত (যার ফলে একাধিক সারি ফেরত দিলে ফল সারিগুলি বহুগুণ করে)। তবে এমনকি নির্দিষ্ট সেট-রিটার্নিং ফাংশনগুলি কেবল FROMক্লজে অনুমোদিত । unnest()Postgres 9.4 বা তারপরে একাধিক পরামিতিগুলির সাথে পছন্দ করুন । ম্যানুয়াল:

এটি কেবল ধারাতে অনুমোদিত FROM;

সুতরাং এটি কাজ করে তবে সহজেই সাবকিউয়ের সাথে প্রতিস্থাপন করা যায় না:

CREATE TABLE tbl (a1 int[], a2 int[]);
SELECT * FROM tbl, unnest(a1, a2) u(elem1, elem2);  -- implicit LATERAL

ধারাটিতে কমা ( ,) এর FROMজন্য সংক্ষিপ্ত স্বরলিপি CROSS JOIN
LATERALটেবিল ফাংশন জন্য স্বয়ংক্রিয়ভাবে ধরে নেওয়া হয়।
এর বিশেষ ক্ষেত্রে সম্পর্কে আরও UNNEST( array_expression [, ... ] ):

মধ্যে ফাংশন সেট করুন SELECTতালিকায়

আপনি পছন্দ করতে সেট ফিরে ফাংশন ব্যবহার করতে পারেন unnest()মধ্যে SELECTসরাসরি তালিকা। এটি SELECTপোস্টগ্রিস 9.6 পর্যন্ত একই তালিকায় এই জাতীয় একাধিক ফাংশনের সাথে অবাক করা আচরণ প্রদর্শন করত । তবে শেষ পর্যন্ত এটি পোস্টগ্রিস 10 দিয়ে স্যানিটাইজ করা হয়েছে এবং এটি এখন একটি বৈধ বিকল্প (এমনকি যদি স্ট্যান্ডার্ড এসকিউএল না হয়)। দেখা:

উপরের উদাহরণে বিল্ডিং:

SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2
FROM   tbl;

তুলনা:

PG 9.6 জন্য dbfiddle এখানে
PG 10 এর জন্য dbfiddle এখানে

ভুল তথ্য পরিষ্কার করুন

ম্যানুয়াল:

জন্য INNERএবং OUTERযোগদানের ধরনের, একটি যোগদানের শর্ত উল্লেখ করা আবশ্যক, যথা ঠিক এক NATURAL, ON join_condition , অথবা USING( join_column [...])। অর্থের জন্য নীচে দেখুন।
কারণ CROSS JOIN, এই ধারাগুলির কোনওটিই উপস্থিত হতে পারে না।

সুতরাং এই দুটি ক্যোয়ারী বৈধ (বিশেষত দরকারী না হলেও):

SELECT *
FROM   tbl t
LEFT   JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t ON TRUE;

SELECT *
FROM   tbl t, LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;

যদিও এটি এক নয়:

SELECT *
FROM   tbl t
LEFT   JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;

কেন এটা @ Andomar এর কোড উদাহরণস্বরূপ সঠিক ( CROSS JOINএকটি শর্ত যোগ দিতে প্রয়োজন হয় না) এবং @ Attila এর হয় অবৈধ ছিল।


কিছু জিনিস রয়েছে যা সাবকিউরিটি ল্যাটারাল জয়িন করতে পারে। উইন্ডো ফাংশন পছন্দ। এখানে যেমন
ইভান ক্যারল

@ ইভানক্রোল: লিঙ্কটিতে আমি কোনও সহযোগিত সাব-কোয়েরি খুঁজে পাইনি। তবে আমি একটি LATERALসাবকোয়ারিতে একটি উইন্ডো ফাংশন প্রদর্শনের জন্য আরও একটি উত্তর যুক্ত করেছি: gis.stackexchange.com/a/230070/7244
এরউইন ব্র্যান্ডসেটেটার

1
ক্লিনার এবং দ্রুত? কিছু ক্ষেত্রে তাত্পর্য দ্রুত। আমার একটি ক্যোয়ারী ছিল যা LATERAL এ স্যুইচ করার পরে কয়েক থেকে কয়েক সেকেন্ড পরে গিয়েছিল।
রোভিকো

51

নন- lateralএবং একটি lateralযোগদানের মধ্যে পার্থক্যটি আপনি বাম হাতের টেবিলের সারিটি দেখতে পারেন কিনা তার মধ্যে রয়েছে। উদাহরণ স্বরূপ:

select  *
from    table1 t1
cross join lateral
        (
        select  *
        from    t2
        where   t1.col1 = t2.col1 -- Only allowed because of lateral
        ) sub

এই "বাহ্যিক সন্ধান" এর অর্থ হল সাবকোয়ারিকে একাধিকবার মূল্যায়ন করতে হবে। সর্বোপরি, t1.col1অনেক মান ধরে নিতে পারে।

বিপরীতে, অ- lateralযোগদানের পরের subquery একবার মূল্যায়ন করা যেতে পারে:

select  *
from    table1 t1
cross join
        (
        select  *
        from    t2
        where   t2.col1 = 42 -- No reference to outer query
        ) sub

যেমনটি ছাড়াই প্রয়োজনীয় lateral, অভ্যন্তরীণ কোয়েরি বাইরের কোয়েরিতে কোনওভাবে নির্ভর করে না। একজন lateralক্যোয়ারিতে একটি একটি উদাহরণ correlatedক্যোয়ারী নিজেই বাইরে সারি সঙ্গে তার সম্পর্ক কারণে জিজ্ঞাস্য।


5
এটি পার্শ্ববর্তী যোগদানের সবচেয়ে পরিষ্কার ব্যাখ্যা।
1valdis

ব্যাখ্যা বুঝতে সহজ, আপনাকে ধন্যবাদ।
আরিলওয়ান

select * from table1 left join t2 using (col1)তুলনা কিভাবে ? শর্তটি / অন ব্যবহারের সাথে যোগ দেওয়া যখন অপর্যাপ্ত হয় তখন তা আমার কাছে অস্পষ্ট late
নং_নাম

9

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

দ্বিতীয়ত, আমার বোধ অনুযায়ী , ল্যাটারাল ব্যবহার না করে subquery ব্যবহার করে আপনি কিছুই করতে পারবেন না। কিন্তু:

নিম্নলিখিত কোয়েরি বিবেচনা করুন।

Select A.*
, (Select B.Column1 from B where B.Fk1 = A.PK and Limit 1)
, (Select B.Column2 from B where B.Fk1 = A.PK and Limit 1)
FROM A 

আপনি এই অবস্থায় পার্শ্বযুক্ত ব্যবহার করতে পারেন।

Select A.*
, x.Column1
, x.Column2
FROM A LEFT JOIN LATERAL (
  Select B.Column1,B.Column2,B.Fk1 from B  Limit 1
) x ON X.Fk1 = A.PK

এই ক্যোয়ারিতে সীমাবদ্ধতার শর্তের কারণে আপনি সাধারণ যোগদান করতে পারবেন না। পার্শ্ববর্তী বা ক্রস প্রয়োগ ব্যবহার করা যেতে পারে যখন সহজ যোগদানের শর্ত না থাকে

পার্শ্বযুক্ত বা ক্রস প্রয়োগের জন্য আরও ব্যবহার রয়েছে তবে এটি আমার মধ্যে পাওয়া সবচেয়ে সাধারণ।


1
ঠিক অবাকভাবে, আমি অবাক হয়েছি কেন PostgreSQL এর lateralপরিবর্তে ব্যবহার করে apply। মাইক্রোসফ্ট সম্ভবত সিনট্যাক্সের পেটেন্ট করেছে?
Andomar

9
@ আন্দোমার আফাইক lateralএসকিউএল স্ট্যান্ডার্ডে রয়েছে তবে applyতা নয়।
মিউ খুব ছোট

এর LEFT JOINজন্য একটি যোগদানের শর্ত প্রয়োজন। আপনি ON TRUEযদি কোনওভাবে সীমাবদ্ধ না রাখতে চান তা তৈরি করুন ।
এরউইন ব্র্যান্ডস্টেটার

এরউইন ঠিক বলেছেন, আপনি যদি একটি cross joinবা onশর্তটি ব্যবহার না করেন তবে আপনি একটি ত্রুটি পাবেন
অ্যান্ডোমার

1
@ অ্যান্ডোমার: এই ভুল তথ্য দ্বারা উত্সাহিত আমি স্পষ্ট করার জন্য আরও একটি উত্তর যুক্ত করেছি।
এরউইন ব্র্যান্ডসটেটার

4

একটি জিনিস যে কেউ নির্দেশ করেনি তা হ'ল আপনি LATERALপ্রতিটি নির্বাচিত সারিতে ব্যবহারকারী-সংজ্ঞায়িত ফাংশন প্রয়োগ করতে ক্যোরিগুলি ব্যবহার করতে পারেন ।

এই ক্ষেত্রে:

CREATE OR REPLACE FUNCTION delete_company(companyId varchar(255))
RETURNS void AS $$
    BEGIN
        DELETE FROM company_settings WHERE "company_id"=company_id;
        DELETE FROM users WHERE "company_id"=companyId;
        DELETE FROM companies WHERE id=companyId;
    END; 
$$ LANGUAGE plpgsql;

SELECT * FROM (
    SELECT id, name, created_at FROM companies WHERE created_at < '2018-01-01'
) c, LATERAL delete_company(c.id);

PostgreSQL এ এই ধরণের জিনিসটি কীভাবে করা যায় তা আমি একমাত্র উপায় the

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