लारवेल में गैर-कुंजी स्तंभ फ़ील्ड के लिए अलग-अलग मान कैसे प्राप्त करें?


94

यह काफी आसान हो सकता है लेकिन पता नहीं कैसे करना है।

मेरे पास एक तालिका है जो किसी विशेष गैर-कुंजी स्तंभ फ़ील्ड के लिए बार-बार मान हो सकती है। मैं क्वेरी बिल्डर या एलोकेंट का उपयोग करके एक SQL क्वेरी कैसे लिख सकता हूं जो उस कॉलम के लिए अलग-अलग मानों के साथ पंक्तियाँ लाएगा?

ध्यान दें कि मैं केवल उस कॉलम को प्राप्त नहीं कर रहा हूं, यह अन्य कॉलम वैल्यू के साथ संयोजन में है, इसलिए distinct()वास्तव में काम नहीं कर सकता है। तो यह प्रश्न मूल रूप से हो सकता है कि मैं उस कॉलम को कैसे निर्दिष्ट करूं जिसे मैं एक क्वेरी में अलग होना चाहता हूं जो distinct()कोई पैरामीटर स्वीकार नहीं करता है?

जवाबों:


116

आपको उपयोग करना चाहिए groupby। क्वेरी बिल्डर में आप इसे इस तरह से कर सकते हैं:

$users = DB::table('users')
            ->select('id','name', 'email')
            ->groupBy('name')
            ->get();

2
मेरे पास एक टेबल "संदेश" (चैट के लिए प्रयुक्त) है, और मैं नवीनतम संदेश प्राप्त करना चाहता हूं जो कि प्रत्येक वार्तालाप से प्रमाणित उपयोगकर्ता को मिला है। GroupBy के उपयोग से मुझे केवल एक संदेश मिल सकता है, लेकिन मुझे पहला संदेश मिलता है, और मुझे अंतिम संदेश चाहिए। ऐसा लगता है कि आदेश काम नहीं करता है।
JCarlosR

10
यदि आप SUM, AVG, MAX और जैसे "समूह द्वारा" कोई भी गणित ऑपरेशन लागू नहीं करना चाहते हैं, तो सही उत्तर नहीं है (आप इसका उपयोग कर सकते हैं, लेकिन आपको इसका उपयोग नहीं करना चाहिए)। आपको अलग का उपयोग करना चाहिए। MySQL में आप एक कॉलम के लिए DISTINCT का उपयोग कर सकते हैं और परिणाम में अधिक कॉलम जोड़ सकते हैं: "DISTINCT नाम, आईडी, उपयोगकर्ताओं से ईमेल का चयन करें"। वाक्पटुता के साथ आप इसे इस $ के साथ कर सकते हैं-> (['नाम', 'आईडी', 'ईमेल']) -> अलग () -> get ();
सेर्गी

2
जब मैं where()इसे तोड़ता हूं, तो मैं इसे कैसे ठीक कर सकता हूं?
tq

1
जब मैं इसका उपयोग करता हूं तो यह 'आईडी' दिखाता है और 'ईमेल' ग्रुपबी में नहीं है () मुझे ग्रुपबी ('आईडी', 'नाम', 'ईमेल') का उपयोग करने की आवश्यकता है। जो उपयोगी नहीं है।
हक़ीक़त

1
नोट करने के लिए कुछ: group byजैसा नहीं है distinct। SQL क्वेरी के अंदर group byकुल कार्यों के व्यवहार को बदल देगा count()distinctऐसे कार्यों के व्यवहार को नहीं बदलेगा, इसलिए आपको अलग-अलग परिणाम मिलते हैं, जिनके आधार पर आप उपयोग करते हैं।
स्कीट

78

एलोकेंट में भी आप इस तरह से क्वेरी कर सकते हैं:

$users = User::select('name')->distinct()->get();


12
प्रश्न विशेष रूप से पूछता हैNote that I am not fetching that column only, it is in conjunction with other column values
हिरणमस्टर

12
@ हिरणमस्टर: ओकेई। हालाँकि, यह उत्तर अभी भी दूसरों द्वारा पारित करने के लिए उपयोगी है ...
पथरोस

3
मेरे लिए उपयोगी नहीं है, विशेष रूप से देख रहा हूँ कि ओपी क्या है। यह एक आसान खोज नहीं है।
धब्बा

1
$users = User::select('column1', 'column2', 'column3')->distinct()->get();
मार्क-हीरो

इसके साथ ही ->orderBy('name')यदि आप इसका उपयोग करना चाहते हैं तो आपको इसकी आवश्यकता है chunk
चिब्यूज ओपटा

26

वाक्पटु में आप इसका उपयोग कर सकते हैं

$users = User::select('name')->groupBy('name')->get()->toArray() ;

GroupBy वास्तव में अलग-अलग मूल्यों को प्राप्त कर रहा है, वास्तव में groupBy समान मूल्यों को श्रेणीबद्ध करेगा, ताकि हम उन पर कुल कार्यों का उपयोग कर सकें। लेकिन इस परिदृश्य में हमारे पास कोई समग्र कार्य नहीं है, हम केवल उस मूल्य का चयन कर रहे हैं जिसके परिणामस्वरूप अलग-अलग मूल्य होंगे


4
यह कैसे काम करता है? क्या GroupBy वास्तव में अलग-अलग उपयोगकर्ता नामों को ला रहा है? क्या आप कृपया थोड़ा और समझा सकते हैं कि यह कैसे ऑप्स की समस्या का जवाब देता है?
फेलिक्स गगनोन-ग्रेनियर 20

हां GroupBy वास्तव में अलग-अलग मूल्यों को प्राप्त कर रहा है, वास्तव में groupBy समान मूल्यों को श्रेणीबद्ध करेगा, ताकि हम उन पर कुल कार्यों का उपयोग कर सकें। लेकिन इस परिदृश्य में हमारे पास कोई समग्र कार्य नहीं है, हम केवल उस मूल्य का चयन कर रहे हैं जिसके परिणामस्वरूप अलग-अलग मूल्य होंगे।
सालार

मैं देख रहा हूँ .. तो, यह मार्सिन के जवाब से अलग कैसे है? एक अलग उत्तर देना ठीक है, जब तक आप यह बता सकते हैं कि यह कैसे अलग है और यह क्या दोष हल करता है :) टिप्पणियों में जवाब देने से परेशान न हों, कृपया प्रासंगिक जानकारी के साथ अपने प्रश्न को सीधे संपादित करें।
फेलिक्स गगनोन-ग्रेनियर

1
परिणाम समान है, यह ओआरएम का उपयोग करने या क्वेरी बिल्डर का उपयोग करने के लिए आपकी परियोजना पर निर्भर करता है, यदि आप उनमें से किसी एक का उपयोग कर रहे हैं, तो उस एक के साथ रहना बेहतर है। इसीलिए मैंने आपके प्रश्न का अलग तरीके से उत्तर दिया।
सालार

खैर, मेरे पास यह मुद्दा है कि, यदि आप अब यह जांचना चाहते हैं कि in_array()फ़ंक्शन का उपयोग करके कोई आइटम मौजूद है , तो यह कभी काम नहीं करता है। इसे ठीक करने के लिए, मैंने ->lists()इसके बजाय (संस्करण 5.2) की कोशिश की । तो, $users = User::select('name')->groupBy('name')->lists('name');php के लिए ठीक काम किया in_array();
रात्रि

19

हालांकि मुझे इसका उत्तर देने में देर हो रही है, एलोकेंट का उपयोग करके अलग-अलग रिकॉर्ड प्राप्त करने के लिए एक बेहतर दृष्टिकोण होगा

$user_names = User::distinct()->get(['name']);

ठीक है, आपने हमें यह दिखाते हुए मूल्य जोड़ दिया है कि कोई भी क्षेत्र के नामों के पैरामेट्स को get()विधि से पास कर सकता है (और मैंने विधि का परीक्षण भी किया है first()), जो select()विधि का उपयोग करने के बराबर है जैसा कि यहां कुछ उत्तरों में दिखाया गया है। हालांकि किसी groupByभी तरह अभी भी उच्चतम स्कोर करने के लिए लगता है। हालांकि यह वास्तव में अलग होगा यदि मैं एकमात्र कॉलम चुन रहा हूं।
गथुओ

प्रदर्शन के अनुसार, अलग-अलग ग्रुपबाय पर स्कोर करने जा रहा है, क्योंकि रिकॉर्ड्स को पहले SQL इंजन में समूह के विपरीत चुना जाएगा। इंजन द्वारा पहले सभी रिकॉर्ड्स का चयन किया जाता है और फिर समूह के द्वारा ..
rsakhale

1
$user_names = User::distinct()->count(['name']);भी काम करता है
बिरा

11

यदि डेटाबेस नियम किसी भी चुनिंदा फ़ील्ड को कुल फ़ंक्शन के बाहर होने की अनुमति नहीं देते हैं, तो समूह द्वारा काम नहीं किया जाएगा। इसके बजाय लार्वा संग्रह का उपयोग करें ।

$users = DB::table('users')
        ->select('id','name', 'email')
        ->get();

foreach($users->unique('name') as $user){
  //....
}

किसी ने कहा कि यह बड़े संग्रह के लिए प्रदर्शन पर बहुत अच्छा नहीं हो सकता है। मैं संग्रह में एक कुंजी जोड़ने की सलाह दूंगा। उपयोग करने की विधि को कीबी कहा जाता है । यह सरल विधि है।

     $users = DB::table('users')
        ->select('id','name', 'email')
        ->get()
        ->keyBy('name');

कीबी आपको और अधिक जटिल चीजों के लिए कॉल बैक फ़ंक्शन जोड़ने की अनुमति देता है ...

     $users = DB::table('users')
        ->select('id','name', 'email')
        ->get()
        ->keyBy(function($user){
              return $user->name . '-' . $user->id;
         });

यदि आपको बड़े संग्रहों पर चलना है, तो इसमें एक कुंजी जोड़कर प्रदर्शन समस्या को हल किया जा सकता है।


आप सही हैं और वास्तव में इस मुद्दे के खिलाफ हूँ ... हालांकि जब तक क्वेरी को निष्पादित नहीं किया जाता है तब तक इंतजार करना और संग्रह में कार्रवाई करना भी आदर्श नहीं है। विशेष रूप से यदि आप पेजिंग पर भरोसा कर रहे हैं, तो आपका ऑपरेशन पेजिनेशन गणना के बाद होगा और प्रति पृष्ठ आइटम गलत होंगे। इसके अलावा, डीबी बड़े डेटा चंक्स पर काम करने के लिए बेहतर है, बल्कि इसे कोड में पुनः प्राप्त करना और संसाधित करना। छोटे डेटा विखंडू के लिए यह एक समस्या से कम होगा
क्रोनोफिश

आपकी एक अच्छी बात है। हो सकता है कि यह विधि बड़े संग्रह पर बहुत अच्छा प्रदर्शन न करे, और यह पृष्ठांकन के लिए काम नहीं करेगा। मुझे लगता है कि एक बेहतर जवाब है कि मेरे पास क्या है।
जेड लिंच

6

ध्यान दें कि groupByजैसा कि ऊपर इस्तेमाल किया गया है, पोस्टग्रेज के लिए काम नहीं करेगा।

का उपयोग करना distinctशायद एक बेहतर विकल्प है - जैसे $users = User::query()->distinct()->get();

यदि आप उपयोग queryकरते हैं तो आप अनुरोध के अनुसार सभी कॉलम चुन सकते हैं।


6

**

लारवेल 5.8 के लिए परीक्षण किया गया

**

चूंकि आप तालिका से सभी कॉलम प्राप्त करना चाहते हैं, आप सभी डेटा एकत्र कर सकते हैं और फिर इसे यूनीक नामक कलेक्शन फ़ंक्शन का उपयोग करके फ़िल्टर कर सकते हैं

// Get all users with unique name
User::all()->unique('name')

या

// Get all & latest users with unique name 
User::latest()->get()->unique('name')

अधिक जानकारी के लिए आप लारवेल कलेक्शन डॉक्यूमेंटेशन देख सकते हैं

संपादित करें: आप अद्वितीय () का उपयोग करके पूर्णता के साथ जारी कर सकते हैं, आपको उपयोगकर्ता तालिका से सबसे पहले डेटा मिलेगा, और फिर लारवेल इसे फ़िल्टर करेगा। यदि आपके पास बहुत सारे उपयोगकर्ता डेटा हैं तो यह तरीका अच्छा नहीं है। आप क्वेरी बिल्डर का उपयोग कर सकते हैं और प्रत्येक फ़ील्ड को कॉल कर सकते हैं जिसका आप उपयोग करना चाहते हैं, उदाहरण:

User::select('username','email','name')->distinct('name')->get();

यह कुशल नहीं है क्योंकि आप db से सभी डेटा पहले प्राप्त करते हैं
रेजर मूरिथी

इसलिए इसे फ़िल्टरिंग कहा जाता है, आप क्वेरी बिल्डर के लिए अलग () का उपयोग कर सकते हैं, लेकिन आप अन्य फ़ील्ड नहीं प्राप्त कर सकते हैं (वैसे भी आप अभी भी चयन के माध्यम से प्रत्येक फ़ील्ड को कॉल करने में सक्षम हैं)। अद्वितीय () का उपयोग करके उनमें से प्रत्येक को कॉल किए बिना सभी फ़ील्ड प्राप्त करने का एकमात्र तरीका है (इस बारे में हम जानते हैं कि पूर्णता के साथ समस्या हो सकती है)।
रॉबी अलियन जया मुलिया

5

$users = User::select('column1', 'column2', 'column3')->distinct()->get();तालिका में अलग-अलग पंक्तियों के लिए सभी तीन युग्मनों को पुनः प्राप्त करता है। आप जितने चाहें उतने कॉलम जोड़ सकते हैं।


3

मैंने पाया कि यह विधि काफी काम कर रही है (मेरे लिए) अद्वितीय मूल्यों के एक फ्लैट सरणी का उत्पादन करने के लिए:

$uniqueNames = User::select('name')->distinct()->pluck('name')->toArray();

यदि आप ->toSql()इस क्वेरी बिल्डर पर भागते हैं , तो आप देखेंगे कि यह इस तरह से एक क्वेरी उत्पन्न करता है:

select distinct `name` from `users`

->pluck()रोशन \ संग्रह lib (एसक्यूएल क्वेरी के माध्यम से नहीं) द्वारा नियंत्रित किया जाता।


1

मेरे पास एक ही समस्या थी जब एक उपयोगकर्ता द्वारा अन्य उपयोगकर्ताओं के साथ किए गए सभी अद्वितीय थ्रेड्स की सूची को पॉप्युलेट करने की कोशिश की गई थी। इसने मेरे लिए चाल चली

Message::where('from_user', $user->id)
        ->select(['from_user', 'to_user'])
        ->selectRaw('MAX(created_at) AS last_date')
        ->groupBy(['from_user', 'to_user'])
        ->orderBy('last_date', 'DESC')
        ->get()


0

उन लोगों के लिए जो मुझे एक ही गलती कर रहे हैं। यहाँ Laravel 5.7 में विस्तृत उत्तर दिया गया है

A. डीबी में रिकॉर्ड

Userfile :: orderBy ( 'created_at', 'desc') -> get () -> toArray ();

Array
(
    [0] => Array
        (
            [id] => 2073
            [type] => 'DL'
            [url] => 'https://i.picsum.photos/12/884/200/300.jpg'
            [created_at] => 2020-08-05 17:16:48
            [updated_at] => 2020-08-06 18:08:38
        )

    [1] => Array
        (
            [id] => 2074
            [type] => 'PROFILE'
            [url] => 'https://i.picsum.photos/13/884/200/300.jpg'
            [created_at] => 2020-08-05 17:20:06
            [updated_at] => 2020-08-06 18:08:38
        )

    [2] => Array
        (
            [id] => 2076
            [type] => 'PROFILE'
            [url] => 'https://i.picsum.photos/13/884/200/300.jpg'
            [created_at] => 2020-08-05 17:22:01
            [updated_at] => 2020-08-06 18:08:38
        )

    [3] => Array
        (
            [id] => 2086
            [type] => 'PROFILE'
            [url] => 'https://i.picsum.photos/13/884/200/300.jpg'
            [created_at] => 2020-08-05 19:22:41
            [updated_at] => 2020-08-06 18:08:38
        )
)

बी वांछित समूहित परिणाम

Userfile :: का चयन करें ( 'प्रकार', 'url', 'updated_at) -> अलग (' प्रकार ') -> get () -> toArray ();

Array
(
    [0] => Array
        (
            [type] => 'DL'
            [url] => 'https://i.picsum.photos/12/884/200/300.jpg'
            [updated_at] => 2020-08-06 18:08:38 
        )

    [1] => Array
        (
            [type] => 'PROFILE'
            [url] => 'https://i.picsum.photos/13/884/200/300.jpg'
            [updated_at] => 2020-08-06 18:08:38
        )
)

इसलिए केवल उन कॉलम को पास करें "select()", जिनमें से मान समान हैं। उदाहरण के लिए 'type','url':। आप अधिक कॉलम जोड़ सकते हैं बशर्ते उनका समान मूल्य हो 'updated_at'

यदि आप पास करने की कोशिश करते हैं "created_at"या "id"अंदर जाते हैं "select()", तो आपको रिकॉर्ड ए के समान मिलेगा क्योंकि वे डीबी में प्रत्येक पंक्ति के लिए अलग हैं।



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