रेल: एक कॉलम से अद्वितीय मानों का चयन करें


238

मेरे पास पहले से ही एक कार्यशील समाधान है, लेकिन मैं वास्तव में जानना चाहूंगा कि यह काम क्यों नहीं करता है:

ratings = Model.select(:rating).uniq
ratings.each { |r| puts r.rating }

यह चयन करता है, लेकिन अनूठे मूल्यों को प्रिंट नहीं करता है, यह डुप्लिकेट सहित सभी मूल्यों को प्रिंट करता है। और यह प्रलेखन में है: http://guides.rubyonrails.org/active_record_querying.html#selecting-specific-fields


जवाबों:


449
Model.select(:rating)

इसका परिणाम Modelवस्तुओं का एक संग्रह है । सादे रेटिंग नहीं। और uniqदेखने के दृष्टिकोण से, वे पूरी तरह से अलग हैं। आप इसका उपयोग कर सकते हैं:

Model.select(:rating).map(&:rating).uniq

या यह (सबसे कुशल)

Model.uniq.pluck(:rating)

# rails 5+
Model.distinct.pluck(:rating)

अपडेट करें

जाहिर है, 5.0.0.1 रेल के रूप में, यह केवल "शीर्ष स्तर" प्रश्नों पर काम करता है, ऊपर की तरह। संग्रह के प्रॉक्सी ("has_many" संबंधों पर काम नहीं करता है, उदाहरण के लिए)।

Address.distinct.pluck(:city) # => ['Moscow']
user.addresses.distinct.pluck(:city) # => ['Moscow', 'Moscow', 'Moscow']

इस मामले में, क्वेरी के बाद कटौती करें

user.addresses.pluck(:city).uniq # => ['Moscow']

मैंने एक: समूह ((रेटिंग)) .collect {| r | r.rating} चूंकि map == इकट्ठा है, मैं आपके द्वारा उपयोग किए गए इस सिंटैक्स के बारे में कहां पढ़ सकता हूं (&: रेटिंग)? मैं इसे रूबी के दस्तावेज में नहीं देखता हूं।
अलेक्जेंड्रेकोस्टा

@ user1261084: .map (&: रेटिंग) को समझने के लिए प्रतीक # to_proc देखें । प्रागडेव बताते हैं
debhur

63
यह ध्यान देने योग्य है कि Model.uniq.pluck(:rating)ऐसा करने का सबसे कुशल तरीका है - यह SQL उत्पन्न करता है जो किसी सरणी पर SELECT DISTINCTलागू .uniqहोने के बजाय उपयोग करता है
मिकी

23
रेल 5 में, Model.uniq.pluck(:rating)होगीModel.distinct.pluck(:rating)
न्यूरोडायनामिक

2
यदि आप has_many संबंध से अनूठे मूल्यों का चयन करना चाहते हैं तो आप हमेशा कर सकते हैंModel.related_records.group(:some_column).pluck(:some_column)
Krzysztof Karski

92

यदि आप उपयोग करने जा रहे हैं Model.select, तो आप केवल उपयोग कर सकते हैं DISTINCT, क्योंकि यह केवल अद्वितीय मान लौटाएगा। यह बेहतर है क्योंकि इसका मतलब है कि यह कम पंक्तियों को लौटाता है और कई पंक्तियों को वापस करने की तुलना में थोड़ा तेज होना चाहिए और फिर पटरियों को अद्वितीय मान लेने के लिए कहना चाहिए।

Model.select('DISTINCT rating')

बेशक, यह प्रदान किया जाता है कि आपका डेटाबेस DISTINCTकीवर्ड को समझता है , और सबसे अधिक चाहिए।


6
Model.select("DISTINCT rating").map(&:rating)बस रेटिंग का एक सरणी पाने के लिए।
क्रिश

रेल 2.3
मिकी

3
हां..यह शानदार काम करता है - हालाँकि, लेकिन यह केवल DISTINCT विशेषता देता है। जब तक आप इसकी पूरी मॉडल वस्तु को अलग-अलग नहीं कर सकते, तब तक आप इसे कैसे लौटा सकते हैं? ताकि आपके पास सभी विशेषताओं में मॉडल में उन सभी तक पहुंच होगी जहां विशेषता अद्वितीय है।
जीरो_कूल

@Jackson_Sandland यदि आप एक मॉडल ऑब्जेक्ट चाहते हैं, तो उसे तालिका में रिकॉर्ड से तत्काल लिया जाना चाहिए। लेकिन आप केवल एक अद्वितीय मूल्य (जो कई रिकॉर्ड हो सकते हैं) से एक रिकॉर्ड का चयन नहीं कर रहे हैं।
बेनिसीमो

69

यह भी काम करता है।

Model.pluck("DISTINCT rating")

मेरा मानना ​​है कि प्लक रूबी 1.9.x और ऊपर है। पिछले संस्करण का उपयोग करने वाले किसी के पास यह नहीं होगा। यदि आप 1.9x और उससे ऊपर के हैं, तो माणिक डॉक्स कहते हैं कि यह भी काम करता है: Model.uniq.pluck (: रेटिंग)
kakubei

6
pluckएक शुद्ध रेल> 3.2 विधि है जिसमें रूबी पर कोई निर्भरता नहीं है 1.9.x देखें apidock.com/rails/v3.2.1/ActiveRecord/Calculations/pluck
डैनियल रिकोस्की


27
Model.uniq.pluck(:rating)

# SELECT DISTINCT "models"."rating" FROM "models"

यह एसक्यूएल स्ट्रिंग्स का उपयोग नहीं करने और तत्काल मॉडल का उपयोग न करने के फायदे हैं


3
यह रेल 5.1 / AR 5.1 => अपरिभाषित विधि `uniq 'के साथ एक त्रुटि फेंकता है
ग्राहम स्लीक

24
Model.select(:rating).uniq

यह कोड 3.2 के बाद से 'DISTINCT' (Array # uniq के रूप में नहीं) के रूप में काम करता है


5
Model.select(:rating).distinct

2
यह एकमात्र आधिकारिक रूप से सही उत्तर है जो सुपर कुशल भी है। हालाँकि, .pluck(:rating)अंत में जोड़ने से यह वही होगा जो ओपी ने पूछा था।
शेहरी

5

अगर मैं सही तरीके से जा रहा हूँ तो:

वर्तमान क्वेरी

Model.select(:rating)

ऑब्जेक्ट की सरणी लौटा रहा है और आपने क्वेरी लिखी है

Model.select(:rating).uniq

uniq को ऑब्जेक्ट की सरणी पर लागू किया जाता है और प्रत्येक ऑब्जेक्ट में अद्वितीय आईडी होती है। यूनीक अपना काम सही ढंग से कर रहा है क्योंकि एरे में प्रत्येक ऑब्जेक्ट यूनीक है।

अलग रेटिंग का चयन करने के कई तरीके हैं:

Model.select('distinct rating').map(&:rating)

या

Model.select('distinct rating').collect(&:rating)

या

Model.select(:rating).map(&:rating).uniq

या

Model.select(:name).collect(&:rating).uniq

एक और बात, पहली और दूसरी क्वेरी: SQL क्वेरी द्वारा अलग-अलग डेटा ढूंढें।

इन प्रश्नों को "लंदन" और "लंदन" माना जाएगा, इसका मतलब है कि यह अंतरिक्ष की उपेक्षा करेगा, इसीलिए यह आपके क्वेरी परिणाम में एक बार 'लंदन' का चयन करेगा।

तीसरा और आगे का प्रश्न:

SQL क्वेरी द्वारा और अलग-अलग डेटा लागू रूबी uniq mehtod के लिए डेटा खोजें। इन प्रश्नों को "लंदन" और "लंदन" अलग माना जाएगा, इसीलिए यह आपके क्वेरी परिणाम में 'लंदन' और 'लंदन' दोनों का चयन करेगा।

कृपया अधिक समझ के लिए संलग्न छवि को पसंद करें और "टूरेड / प्रतीक्षा कर रहे आरएफपी" पर एक नज़र डालें।

यहां छवि विवरण दर्ज करें


6
map& collectएक ही विधि के लिए उपनाम हैं, दोनों के लिए उदाहरण प्रदान करने की आवश्यकता नहीं है।
एडम लाससेक 5'14

4

कुछ जवाबों को ध्यान में नहीं है कि ओपी मूल्यों की एक सरणी चाहता है

यदि आपके मॉडल में हजारों रिकॉर्ड हैं, तो अन्य उत्तर अच्छी तरह से काम नहीं करते हैं

उस ने कहा, मुझे लगता है कि एक अच्छा जवाब है:

    Model.uniq.select(:ratings).map(&:ratings)
    => "SELECT DISTINCT ratings FROM `models` " 

क्योंकि, पहले आप मॉडल की एक सरणी उत्पन्न करते हैं (चयन के कारण कम आकार के साथ), फिर आप केवल उन विशेषताओं को निकालते हैं जिन्हें उन चयनित मॉडल (रेटिंग्स) ने बनाया है


3

अगर कोई भी मोंगॉयड के साथ समान है, तो वह है

Model.distinct(:rating)

यह अब काम नहीं करता है, यह अब कई गुना रिटर्न देता है।
EUPHORAY

अलग
dowi

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.