আমি কীভাবে (বা আমি) একাধিক কলামে DISTINCT নির্বাচন করতে পারি?


415

আমাকে একটি সারণী থেকে সমস্ত সারি পুনরুদ্ধার করতে হবে যেখানে দুটি কলাম সংযুক্ত সমস্ত পৃথক all সুতরাং আমি চাই যে সমস্ত বিক্রয় একই দিনে একই দামে ঘটেছিল অন্য কোনও বিক্রয় নেই। দিন এবং দামের ভিত্তিতে অনন্য যে বিক্রয়গুলি সক্রিয় স্থিতিতে আপডেট হবে।

তাই আমি ভাবছি:

UPDATE sales
SET status = 'ACTIVE'
WHERE id IN (SELECT DISTINCT (saleprice, saledate), id, count(id)
             FROM sales
             HAVING count = 1)

তবে আমার মস্তিষ্ক তার থেকে আরও দূরে যেতে ব্যথা করে।

উত্তর:


436
SELECT DISTINCT a,b,c FROM t

হয় মোটামুটিভাবে সমতূল্য:

SELECT a,b,c FROM t GROUP BY a,b,c

এটি আরও শক্তিশালী হওয়ায় গ্রোপ বাই সিনট্যাক্সের সাথে অভ্যস্ত হওয়া ভাল ধারণা।

আপনার প্রশ্নের জন্য, আমি এটি এটি করব:

UPDATE sales
SET status='ACTIVE'
WHERE id IN
(
    SELECT id
    FROM sales S
    INNER JOIN
    (
        SELECT saleprice, saledate
        FROM sales
        GROUP BY saleprice, saledate
        HAVING COUNT(*) = 1 
    ) T
    ON S.saleprice=T.saleprice AND s.saledate=T.saledate
 )

117
এই কোয়েরিটি সঠিক এবং এখন বছরের জন্য গ্রহণযোগ্য হয়ে উঠেছে, তবে এটি অত্যন্ত অদক্ষ এবং অযৌক্তিক। এটি ব্যবহার করবেন না। আমি অন্য উত্তরে একটি বিকল্প এবং কিছু ব্যাখ্যা সরবরাহ করেছি।
এরউইন ব্র্যান্ডসটেটার

1
স্বতন্ত্র A, B, T থেকে গ নির্বাচন না করা হয় অবিকল একটি, B, C নির্বাচন একই জিনিস A, B, টি গ্রুপ থেকে গ?
ফামারগার

8
সরল মামলার জন্য @ ফাফারগার, তবুও শব্দার্থগতভাবে তাদের আলাদা অর্থ রয়েছে এবং আরও বড় ক্যোয়ারী তৈরি করার সময় আপনি এই পদক্ষেপের জন্য কী করতে পারেন সে ক্ষেত্রে এগুলি ভিন্ন। এছাড়াও, প্রযুক্তি ফোরামে থাকা লোকেরা প্রায়শই জিনিসগুলি সম্পর্কে অত্যন্ত প্যাড্যান্টিক হতে পারে, আমি প্রায়শই এই প্রসঙ্গে আমার পোস্টগুলিতে নয়েজ শব্দ যুক্ত করা দরকারী বলে মনে করি।
জোয়েল কোহোর্ন

344

আপনি যদি এখনও পর্যন্ত উত্তরগুলি একসাথে রেখে, পরিষ্কার এবং উন্নত করেন তবে আপনি এই উচ্চতর ক্যোয়ারিতে পৌঁছে যাবেন:

UPDATE sales
SET    status = 'ACTIVE'
WHERE  (saleprice, saledate) IN (
    SELECT saleprice, saledate
    FROM   sales
    GROUP  BY saleprice, saledate
    HAVING count(*) = 1 
    );

যা অনেক বেশি তাদের উভয়ের তুলনায় দ্রুত। 10 - 15 ফ্যাক্টর (পোস্টগ্র্রেএসকিউএল 8.4 এবং 9.1 এ আমার পরীক্ষাগুলিতে) বর্তমানে গৃহীত উত্তরের জন্য পারফরম্যান্সকে অনুগ্রহ করে।

তবে এটি এখনও সর্বোত্তম থেকে অনেক দূরে। NOT EXISTSআরও ভাল পারফরম্যান্সের জন্য একটি (অ্যান্টি-) আধা-যুক্ত ব্যবহার করুন। EXISTSস্ট্যান্ডার্ড এসকিউএল, সর্বদা চিরকাল ছিল (কমপক্ষে পোস্টগ্র্যাস এসকিউএল .2.২ থেকে এই প্রশ্নটি জিজ্ঞাসা করার অনেক আগে) এবং উপস্থাপিত প্রয়োজনীয়তাগুলি পুরোপুরি ফিট করে:

UPDATE sales s
SET    status = 'ACTIVE'
WHERE  NOT EXISTS (
   SELECT FROM sales s1                     -- SELECT list can be empty for EXISTS
   WHERE  s.saleprice = s1.saleprice
   AND    s.saledate  = s1.saledate
   AND    s.id <> s1.id                     -- except for row itself
   )
AND    s.status IS DISTINCT FROM 'ACTIVE';  -- avoid empty updates. see below

ডিবি <> ফিডল এখানে
পুরানো এসকিউএল ফিডল

সারি সনাক্তকরণের জন্য অনন্য কী key

টেবিলের জন্য আপনার কাছে প্রাথমিক বা অনন্য কী না থাকলে ( idউদাহরণস্বরূপ) আপনি ctidএই ক্যোয়ারির উদ্দেশ্যে (তবে কিছু অন্যান্য উদ্দেশ্যে নয়) সিস্টেম কলামের বিকল্প নিতে পারেন :

   AND    s1.ctid <> s.ctid

প্রতিটি টেবিলের একটি প্রাথমিক কী থাকা উচিত। আপনার যদি না থাকে তবে একটি যুক্ত করুন। আমি একটি serialবা একটি পরামর্শIDENTITY পোস্টগ্রিস 10+ এ কলাম ।

সম্পর্কিত:

এটা কিভাবে দ্রুত?

EXISTSঅ্যান্টি-সেমি- জয়েন্টের সাবকিউরিটি প্রথম ডুপটি পাওয়া মাত্রই মূল্যায়ন করা বন্ধ করতে পারে (আরও দেখার পক্ষে কোনও অর্থ নেই)। কয়েকটি অনুলিপি সহ বেস টেবিলের জন্য এটি কেবলমাত্র হালকাভাবে আরও দক্ষ। সদৃশ প্রচুর সঙ্গে এই হয়ে উপায় আরও দক্ষ।

খালি আপডেটগুলি বাদ দিন

ইতিমধ্যে status = 'ACTIVE'এই আপডেট থাকা সারিগুলির জন্য কোনও পরিবর্তন হবে না, তবে এখনও সম্পূর্ণ ব্যয়ে একটি নতুন সারি সংস্করণ প্রবেশ করান (ছোট ব্যতিক্রমগুলি প্রয়োগ হবে) apply সাধারণত, আপনি এটি চান না। WHEREএটি এড়াতে এবং আরও দ্রুততর করার জন্য উপরের মতো প্রদর্শিত আরও একটি শর্ত যুক্ত করুন :

যদি statusসংজ্ঞায়িত করা হয় তবে আপনি এটিকে NOT NULLসহজ করতে পারবেন:

AND status <> 'ACTIVE';

কলামের ডেটা ধরণের অবশ্যই <>অপারেটরকে সমর্থন করবে । কিছু প্রকারের মতো jsonনয়। দেখা:

NULL পরিচালনার ক্ষেত্রে সূক্ষ্ম পার্থক্য

এই ক্যোয়ারী ( বর্তমানে জোয়েলের গৃহীত উত্তরের মতো নয় ) নুল মানকে সমান হিসাবে বিবেচনা করে না। নিম্নলিখিত দুটি সারি (saleprice, saledate)"স্বতন্ত্র" হিসাবে যোগ্যতা অর্জন করবে (যদিও মানুষের চোখের সাথে অভিন্ন দেখায়):

(123, NULL)
(123, NULL)

এছাড়াও একটি অনন্য সূচক এবং অন্য কোথাও পাস করে, যেহেতু NULL মানগুলি এসকিউএল স্ট্যান্ডার্ড অনুযায়ী সমান তুলনা করে না। দেখা:

OTOH, GROUP BY, DISTINCTবা DISTINCT ON ()সমান হিসাবে আচরণ শূন্য মান। আপনি কী অর্জন করতে চান তার উপর নির্ভর করে একটি উপযুক্ত ক্যোয়ারী স্টাইল ব্যবহার করুন। আপনি এখনও এই দ্রুত কোয়েরিটিকে NUL তুলনা সমান করার জন্য কোনও বা সমস্ত তুলনার IS NOT DISTINCT FROMপরিবর্তে এর সাথে ব্যবহার =করতে পারেন। আরও:

যদি সমস্ত কলামের তুলনা করা হয় তা সংজ্ঞায়িত করা হয় NOT NULL, তবে মতবিরোধের কোনও জায়গা নেই।


16
ভাল উত্তর. আমি একজন স্কিএল সার্ভার লোক, সুতরাং একটি আইএন () চেক দিয়ে টিপল ব্যবহার করার প্রথম পরামর্শটি আমার কাছে ঘটে না। বিদ্যমান নেই পরামর্শটি সাধারণত অভ্যন্তরীণ জোড়ার মতো স্কিএল সার্ভারে একই কার্যকরকরণ পরিকল্পনার সাথে শেষ হয়।
জোয়েল কোহোর্ন

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

2
@ আলাইরোক: আপনি কোথায় পেলেন? পোস্টগ্রিসের জন্য, বিপরীতটি সত্য। সমস্ত সারি গণনা করার সময়,count(*) হয় আরো তুলনায় দক্ষ count(<expression>)। এটা চেষ্টা করুন. সামগ্রিক ফাংশনের এই বৈকল্পিকের জন্য পোস্টগ্রিসের দ্রুত প্রয়োগ রয়েছে implementation আপনি পোস্টগ্র্রেসকে অন্য কিছু আরডিবিএমএসের সাথে বিভ্রান্ত করছেন?
এরউইন ব্র্যান্ডসেটেটার

6
@ আলাইরোক: আমি সেই পৃষ্ঠাটির সহ-লেখক হতে পেরেছি এবং এটি সাজানোর কিছুই বলে না।
এরউইন ব্র্যান্ডসটেটার

2
@ এরউইন ব্র্যান্ডসটেটার, আপনি সর্বদা স্ট্যাক জুড়ে আপনার উত্তরগুলি নিয়ে পয়েন্টে রয়েছেন। আপনি সারা বছর ধরে প্রায় অভাবনীয় উপায়ে সহায়তা করেছেন। এই উদাহরণ হিসাবে, আমি আমার সমস্যা সমাধানের জন্য কয়েকটি ভিন্ন উপায় জানতাম, তবে আমি দেখতে চেয়েছিলাম যে কেউ সম্ভাবনার মধ্যে দক্ষতা পরীক্ষা করেছেন। ধন্যবাদ.
ওয়ান্ডারার

24

আপনার ক্যোয়ারিতে সমস্যাটি হ'ল গ্রুপ বাই ক্লজটি ব্যবহার করার সময় (যা আপনি মূলত স্বতন্ত্র ব্যবহার করেই করেন) আপনি কেবলমাত্র কলামগুলিই ব্যবহার করতে পারেন যা আপনি ফাংশন অনুসারে বা গোষ্ঠীগুলিকে দলবদ্ধ করেন। সম্ভাব্য বিভিন্ন মান রয়েছে বলে আপনি কলাম আইডি ব্যবহার করতে পারবেন না। আপনার ক্ষেত্রে হ্যাভিং ধারাটির কারণে সবসময় কেবল একটি মান থাকে তবে বেশিরভাগ আরডিবিএমএস এটি স্বীকৃতি দেওয়ার জন্য যথেষ্ট স্মার্ট নয়।

এটি অবশ্য কাজ করে (এবং যোগদানের প্রয়োজন নেই):

UPDATE sales
SET status='ACTIVE'
WHERE id IN (
  SELECT MIN(id) FROM sales
  GROUP BY saleprice, saledate
  HAVING COUNT(id) = 1
)

আপনি এমআইএন এর পরিবর্তে ম্যাক্স বা এভিজিও ব্যবহার করতে পারেন, কেবলমাত্র একটি ম্যাচের সারি থাকলে কলামটির মান ফেরত দেয় এমন ফাংশনটি ব্যবহার করা গুরুত্বপূর্ণ।


1

আমি একটি কলাম 'GrondOfLucht' থেকে স্বতন্ত্র মানগুলি নির্বাচন করতে চাই তবে সেগুলি ক্রম অনুসারে বাছাই করা উচিত কলাম 'বাছাই' অনুসারে। আমি কেবল একটি কলাম ব্যবহার করে স্বতন্ত্র মান পেতে পারি না

Select distinct GrondOfLucht,sortering
from CorWijzeVanAanleg
order by sortering

এটি কলামটি 'বাছাই' দেবে এবং কারণ 'গ্রানডফ্লুচট' এবং 'সর্টিং' অনন্য নয়, ফলস্বরূপ সমস্ত সারি হবে।

'বাছাই' দ্বারা প্রদত্ত ক্রমে 'GrondOfLucht' রেকর্ড নির্বাচন করতে গ্রুপ ব্যবহার করুন

SELECT        GrondOfLucht
FROM            dbo.CorWijzeVanAanleg
GROUP BY GrondOfLucht, sortering
ORDER BY MIN(sortering)

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

0

যদি আপনার ডিবিএমএস এই জাতীয় একাধিক কলামের সাথে স্বতন্ত্র সমর্থন না করে:

select distinct(col1, col2) from table

সাধারণভাবে একাধিক নির্বাচন নিরাপদে সম্পাদন করা যেতে পারে:

select distinct * from (select col1, col2 from table ) as x

যেহেতু এটি বেশিরভাগ ডিবিএমএসে কাজ করতে পারে এবং আপনি গ্রুপিং কার্যকারিতা এড়িয়ে যাচ্ছেন সমাধান হিসাবে এটি গ্রুপের চেয়ে দ্রুত হবে বলে আশা করা হচ্ছে।

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