বিতরণ থেকে কি কোনওরকম বা সকলের সাথে একত্রিত করা যায়?


13

পোস্টগ্রিসের IS DISTINCT FROMসাথে একত্রিত হওয়ার উপায় ANYবা একই ফলাফল পাওয়ার কোনও অন্য ঝরঝরে উপায়?

select count(*)
from (select 'A' foo union all select 'Z' union all select null) z
where foo <> any(array[null, 'A']);

 count
-------
     1
(1 row)

select count(*)
from (select 'A' foo union all select 'Z' union all select null) z
where foo is distinct from any(array[null, 'A']);  

ERROR:  syntax error at or near "any"
LINE 3: where foo is distinct from any(array[null, 'A']);
                                   ^

উত্তর:


7

সম্ভবত এটির মতো :

select foo
     , exists (values (null), ('A') except select foo) chk_any
     , not exists (values (null), ('A') intersect select foo) chk_all
from ( values ('A'),('Z'),(null) ) z(foo);

 foo | chk_any | chk_all
-----+---------+---------
 A   | t       | f
 Z   | t       | t
     | t       | f

লক্ষ্য করুন না শুধুমাত্র null"অ্যারে" এ কিন্তু nullzএই ভাবে তুলনা করা হচ্ছে।


13

এটিকে ব্যাকরণের সমস্যা হিসাবে দেখলে এটি ANYসংজ্ঞায়িত করা হয় ( সারি এবং অ্যারে তুলনায় ):

এক্সপ্রেশন অপারেটর যে কোনও (অ্যারে এক্সপ্রেশন)

তবে is distinct fromঅপারেটর নয়, তুলনা অপারেটরগুলিতে যেমন বলা হয়েছে এটি একটি "কনস্ট্রাক্ট" :

যখন এই আচরণটি উপযুক্ত না হয়, তখন কনস্ট্রাক্টস থেকে IS [নয়] DISTINCT ব্যবহার করুন

যেহেতু পোস্টগ্রিসকিউএল-র ব্যবহারকারী-সংজ্ঞায়িত অপারেটর রয়েছে, আমরা এই উদ্দেশ্যে একটি অপারেটর / ফাংশন কম্বো সংজ্ঞায়িত করতে পারি:

create function is_distinct_from(text, text) returns bool as 
'select $1 is distinct from $2;' language sql;

create operator <!> (
 procedure=is_distinct_from(text,text),
 leftarg=text, rightarg=text
);

তারপরে এটি পূর্ববর্তী হতে পারে ANY:

select count(*)
from (select 'A' foo union all select 'Z' union all select null) z
where foo <!> any(array[null, 'A']);  
 গণনা 
-------
     3
(1 সারি)

1
দুর্দান্ত, অন্তর্দৃষ্টিপূর্ণ উত্তর।
এরউইন ব্র্যান্ডসেটেটার

আমি অবশ্যই প্রস্তাবিত কাজের তুলনায় এটি অবশ্যই অনেক বেশি উচ্চতর, বিশেষত @ এরউইনের উন্নতির সাথে।
অ্যান্ড্রি এম

এই উত্তর এবং @ এরউইনের প্রস্তাবিত টুইটগুলি সত্যিই দুর্দান্ত। আমি অ্যান্ডিরিকে গ্রহণ করছি তবে এটি ব্যক্তিগত পছন্দের বিষয় মাত্র: আমি নিশ্চিত যে অনেকে আপনার কমনীয়তা পছন্দ করবে।
জ্যাক বলেছেন

@ জ্যাকডুগ্লাস: আমি স্ট্যান্ডার্ড অপারেটরগুলির সাথে একটি বিকল্প সমাধান যুক্ত করেছি।
এরউইন ব্র্যান্ডসেটেটার

এটি দুর্ভাগ্যজনক ... সমস্ত উদ্দেশ্য এবং উদ্দেশ্যে, IS DISTINCT FROMঅপারেটর হওয়া উচিত নয় ? শব্দার্থক সমস্যার চেয়ে পার্সারের প্রযুক্তিগত সীমাবদ্ধতার মতো মনে হচ্ছে।
অ্যান্ডি

10

অপারেটর

এটি @ ড্যানিয়েলের চালাক অপারেটরটির উপর নির্মাণ করছে ।
এটিতে থাকাকালীন পলিমারফিক প্রকারগুলি ব্যবহার করে ফাংশন / অপারেটর কম্বো তৈরি করুন । তারপরে এটি যে কোনও প্রকারের জন্য কাজ করে - ঠিক যেমন কনস্ট্রাক্ট।
এবং ফাংশন করা IMMUTABLE

CREATE FUNCTION is_distinct_from(anyelement, anyelement)
  RETURNS bool LANGUAGE sql IMMUTABLE AS 
'SELECT $1 IS DISTINCT FROM $2';

CREATE OPERATOR <!> (
  PROCEDURE = is_distinct_from(anyelement,anyelement),
  LEFTARG  = anyelement
, RIGHTARG = anyelement
);

সিম্বহাউন্ড সহ একটি দ্রুত অনুসন্ধান খালি এসেছিল, তাই অপারেটরটি মডিউলগুলির কোনওরূপে<!> ব্যবহৃত হবে বলে মনে হয় না।

আপনি যদি এই অপারেটরটিকে প্রচুর পরিমাণে ব্যবহার করতে চলেছেন তবে ক্যোয়ারী পরিকল্পনাকারীকে সহায়তা করার জন্য আপনি আরও কিছু বেরিয়ে যেতে পারেন ( যেমন কোনও মন্তব্যে প্রস্তাবিত হারিয়ে যাওয়া )। প্রারম্ভিকদের জন্য, আপনি ক্যোয়ারী অপ্টিমাইজারকে সহায়তা করার জন্য ক্লজ COMMUTATORএবং NEGATORক্লজগুলি যুক্ত করতে পারেন। CREATE OPERATORউপরে এটির সাথে প্রতিস্থাপন করুন :

CREATE OPERATOR <!> (
  PROCEDURE = is_distinct_from(anyelement,anyelement),
  LEFTARG  = anyelement
, RIGHTARG = anyelement
, COMMUTATOR = <!>
, NEGATOR = =!=
);

এবং যোগ কর:

CREATE FUNCTION is_not_distinct_from(anyelement, anyelement)
  RETURNS bool LANGUAGE sql IMMUTABLE AS 
'SELECT $1 IS NOT DISTINCT FROM $2';

CREATE OPERATOR =!= (
  PROCEDURE = is_not_distinct_from(anyelement,anyelement),
  LEFTARG  = anyelement
, RIGHTARG = anyelement
, COMMUTATOR = =!=
, NEGATOR = <!>
);

তবে অতিরিক্ত ধারাগুলি হাতের ব্যবহারের ক্ষেত্রে সহায়তা করবে না এবং সরল সূচকগুলি এখনও ব্যবহার করা হবে না। এটি অর্জন করা অনেক বেশি পরিশীলিত। (আমি চেষ্টা করিনি।) বিশদটির জন্য ম্যানুয়ালটিতে "অপারেটর অপটিমাইজেশন তথ্য" অধ্যায়টি পড়ুন ।

পরীক্ষা ক্ষেত্রে

অ্যারেতে সমস্ত মান একরকম হলেই প্রশ্নে পরীক্ষার কেস সফল হতে পারে। প্রশ্নে অ্যারের জন্য ( '{null,A}'::text[]) ফলাফল সর্বদা সত্য। এটা কি উদ্দেশ্য? আমি "সকলের থেকে ডায়াস্টিন্ট" এর জন্য আরও একটি পরীক্ষা যুক্ত করেছি:

SELECT foo
     , foo <!> ANY ('{null,A}'::text[]) AS chk_any
     , foo <!> ALL ('{null,A}'::text[]) AS chk_all
FROM (
   VALUES ('A'),('Z'),(NULL)
   ) z(foo)

 foo | chk_any | chk_all
-----+---------+---------
 A   | t       | f
 Z   | t       | t
     | t       | f

স্ট্যান্ডার্ড অপারেটরগুলির সাথে বিকল্প

foo IS DISTINCT FROM ANY (test_arr) -- illegal syntax

করতে প্রায় থেকে অনুবাদ করা

foo = ALL (test_arr) IS NOT TRUE

foo = ALL (test_arr) উৎপাদনের ...

TRUE .. যদি সমস্ত উপাদান হয় foo
FALSE.. যদি কোনও NOT NULLউপাদান হয় <> foo
NULL .. যদি কমপক্ষে একটি উপাদান থাকে IS NULLএবং কোনও উপাদান হয় না<> foo

সুতরাং, বাকি কোণার কেসটি কোথায়
- foo IS NULL
- এবং উপাদানগুলি test_arrব্যতীত কিছুই থাকে না NULL

উভয়কেই যদি উড়িয়ে দেওয়া যায় তবে আমাদের কাজ শেষ। সুতরাং, সাধারণ পরীক্ষাটি ব্যবহার করুন যদি
- কলামটি সংজ্ঞায়িত হয় NOT NULL
- বা আপনি জানেন অ্যারে সব ন্যূনসুটি হয় না।

অন্য, অতিরিক্ত পরীক্ষা:

AND ('A' = ALL(test_arr) IS NOT NULL OR 
     'B' = ALL(test_arr) IS NOT NULL OR
     foo IS NOT NULL)

যেখানে 'A'এবং 'B'যে কোনও স্বতন্ত্র মান হতে পারে । এসও সম্পর্কিত এই সম্পর্কিত প্রশ্নের অধীনে ব্যাখ্যা এবং বিকল্পগুলি:
পোস্টগ্রাইএসকিউএল-এ সমস্ত নূরে রয়েছে

আবার, যদি আপনি এমন কোনও মান সম্পর্কে জানেন যা বিদ্যমান থাকতে পারে না test_arr, উদাহরণস্বরূপ খালি স্ট্রিংটি '', আপনি এখনও সহজ করতে পারেন:

AND ('' = ALL(test_arr) IS NOT NULL OR
     foo IS NOT NULL)

সমস্ত সংমিশ্রণের জন্য পরীক্ষা করার জন্য এখানে একটি সম্পূর্ণ টেস্ট ম্যাট্রিক্স:

SELECT foo, test_arr
     , foo = ALL(test_arr) IS NOT TRUE  AS test_simple
     , foo = ALL(test_arr) IS NOT TRUE
       AND ('A' = ALL(test_arr) IS NOT NULL OR
            'B' = ALL(test_arr) IS NOT NULL OR 
            foo IS NOT NULL)            AS test_sure 
FROM (
   VALUES ('A'),('Z'),(NULL)
   ) v(foo)
CROSS JOIN (
   VALUES ('{null,A}'::text[]),('{A,A}'),('{null,null}')
   ) t(test_arr)

 foo |  test_arr   | test_simple | test_sure
-----+-------------+-------------+-----------
 A   | {NULL,A}    | t           | t
 A   | {A,A}       | f           | f   -- only TRUE case
 A   | {NULL,NULL} | t           | t
 Z   | {NULL,A}    | t           | t
 Z   | {A,A}       | t           | t
 Z   | {NULL,NULL} | t           | t
     | {NULL,A}    | t           | t
     | {A,A}       | t           | t
     | {NULL,NULL} | t           | f   -- special case

এটি অ্যান্ড্রির EXCEPTসমাধানের চেয়ে কিছুটা ভারবস , তবে এটি যথেষ্ট দ্রুত।


তৈরি করার সময় OPERATOR, COMMUTATOR(এবং NEGATORসম্ভবত বিপরীত IS NOT DISTINCT FROMঅপারেটর দিয়ে) শর্তটি সরবরাহ করা উচিত? postgresql.org/docs/current/static/xoper-optimization.html
হারানো ঘোড়া

1
@ লস্টহর্স: আমি এটিকে সম্বোধন করে কিছুটা যুক্ত করেছি।
এরউইন ব্র্যান্ডস্টেটার

আমি এই অপারেটরটি অ্যাপ_স্ট্যাটাস (পূর্ণসংখ্যার) উপর নির্ভর করে রেকর্ডগুলি অপসারণ করতে ব্যবহার করছি app_status <!> any(array[3,6])। দুর্ভাগ্যক্রমে, এটি রেকর্ডগুলিতে কোনও প্রভাব ফেলে না। এটি পূর্ণসংখ্যার সাথে কাজ করে?
এম হাবিব

@ এম হাবিব: দয়া করে আপনার প্রশ্নটিকে নতুন প্রশ্ন হিসাবে জিজ্ঞাসা করুন । (সমস্ত প্রাসঙ্গিক বিশদ সহ!) আপনি প্রসঙ্গের জন্য সর্বদা এটির সাথে লিঙ্ক করতে পারেন - এবং ফিরে লিঙ্ক করতে এখানে একটি মন্তব্য ड्रপ করতে পারেন।
এরউইন ব্র্যান্ডসটেটার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.