क्वेरी बिल्डर या एलोक्वेंट का उपयोग करके अतिरिक्त शर्तों के साथ एक जोइन


93

मैं लारवेल क्वेरी बिल्डर के साथ JOIN क्वेरी का उपयोग करके एक शर्त जोड़ने की कोशिश कर रहा हूं।

<?php

$results = DB::select('
       SELECT DISTINCT 
          *
          FROM 
             rooms 
                LEFT JOIN bookings  
                   ON rooms.id = bookings.room_type_id
                  AND (  bookings.arrival between ? and ?
                      OR bookings.departure between ? and ? )
          WHERE
                bookings.room_type_id IS NULL
          LIMIT 20',
    array('2012-05-01', '2012-05-10', '2012-05-01', '2012-05-10')
);

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

$results = DB::table('rooms')
    ->distinct()
    ->leftJoin('bookings', function ($join) {
        $join->on('rooms.id', '=', 'bookings.room_type_id');
    })
    ->whereBetween('arrival', array('2012-05-01', '2012-05-10'))
    ->whereBetween('departure', array('2012-05-01', '2012-05-10'))
    ->where('bookings.room_type_id', '=', null)
    ->get();

यह Laravel द्वारा उत्पन्न क्वेरी है:

select distinct * from `room_type_info`
    left join `bookings` 
on `room_type_info`.`id` = `bookings`.`room_type_id` 
where `arrival` between ? and ? 
    and `departure` between ? and ? 
    and `bookings`.`room_type_id` is null

जैसा कि आप देख सकते हैं, क्वेरी आउटपुट में संरचना नहीं है (विशेषकर JOIN स्कोप के तहत)। क्या JOIN के तहत अतिरिक्त शर्तें जोड़ना संभव है?

मैं लारवेल के क्वेरी बिल्डर का उपयोग करके एक ही क्वेरी कैसे बना सकता हूं (यदि संभव हो) क्या एलक्वेंट का उपयोग करना बेहतर है, या डीबी के साथ रहना चाहिए :: चयन?

जवाबों:


139
$results = DB::table('rooms')
                     ->distinct()
                     ->leftJoin('bookings', function($join)
                         {
                             $join->on('rooms.id', '=', 'bookings.room_type_id');
                             $join->on('arrival','>=',DB::raw("'2012-05-01'"));
                             $join->on('arrival','<=',DB::raw("'2012-05-10'"));
                             $join->on('departure','>=',DB::raw("'2012-05-01'"));
                             $join->on('departure','<=',DB::raw("'2012-05-10'"));
                         })
                     ->where('bookings.room_type_id', '=', NULL)
                     ->get();

यह निश्चित नहीं है कि अगर लार्वा में शामिल होने के लिए क्लॉज के बीच जोड़ा जा सकता है।

टिप्पणियाँ:

  • DB::raw() Laravel को वापस उद्धरण नहीं देने का निर्देश देता है।
  • तरीकों में शामिल होने के लिए एक बंद गुजर करके आप अधिक जोड़ सकते हैं यह करने के लिए शर्तों में शामिल होने, on()जोड़ देगा ANDहालत और orOn()जोड़ देगा ORहालत।

जवाब के लिए धन्यवाद। दुर्भाग्य से, उत्पन्न क्वेरी थोड़ा अलग है क्योंकि ज्वाइन कंडीशन में अब इसके and arrival >= ? and arrival <= ? and departure >= ? and departure <= ?बजाय AND ( r.arrival between ? and ? OR r.departure between ? and ? )(कृपया ORक्लॉज़ नोटिस करें )। यह परिणामी पंक्तियों को जोड़ता है जो कि नहीं होना चाहिए। मुझे लगता है कि QB का उपयोग करके सभी प्रकार की स्थितियों को उत्पन्न करना संभव नहीं है।
देदे

1
वास्तव में मैंने देखा कि? को क्लॉस में नहीं जोड़ा गया है। ON में वे मान पैरामीटर नहीं हैं और SQL इंजेक्शन से सुरक्षित नहीं हैं। मैंने एक प्रश्न पोस्ट किया है जो समाधान का पता लगाने की कोशिश कर रहा है।
प्राग्रामर

3
यह मूल प्रश्न का उत्तर नहीं देता था जो इस प्रतिक्रिया में अनदेखा था या एक खंड था।
आयनोंचो

सही समाधान। बस एक मूल्य का उपयोग करते समय DB :: कच्चे का उपयोग करना याद रखें, अन्यथा लारवेल (कम से कम 5.6.29 में) वापस उद्धरण जोड़ें और लक्ष्य को "तोड़ें"।
एड्रियन हर्नांडेज-लोपेज

35

आप उन ब्रैकेट को बाईं ओर से जोड़ सकते हैं:

LEFT JOIN bookings  
               ON rooms.id = bookings.room_type_id
              AND (  bookings.arrival between ? and ?
                  OR bookings.departure between ? and ? )

है

->leftJoin('bookings', function($join){
    $join->on('rooms.id', '=', 'bookings.room_type_id');
    $join->on(DB::raw('(  bookings.arrival between ? and ? OR bookings.departure between ? and ? )'), DB::raw(''), DB::raw(''));
})

फिर आपको इस SO पोस्ट में वर्णित "setBindings" का उपयोग करके बाद में बाइंडिंग सेट करना होगा: एक मॉडल पर उपयोग किए जाने वाले Laravel में कच्चे DB क्वेरी के लिए मापदंडों को कैसे बांधें?

यह सुंदर नहीं है, लेकिन यह काम करता है।


32

यदि आपके पास कुछ परम हैं, तो आप ऐसा कर सकते हैं।

    $results = DB::table('rooms')
    ->distinct()
    ->leftJoin('bookings', function($join) use ($param1, $param2)
    {
        $join->on('rooms.id', '=', 'bookings.room_type_id');
        $join->on('arrival','=',DB::raw("'".$param1."'"));
        $join->on('arrival','=',DB::raw("'".$param2."'"));

    })
    ->where('bookings.room_type_id', '=', NULL)
    ->get();

और फिर अपनी क्वेरी वापस करें

$ परिणाम लौटाएँ;


23

इस तरह sql क्वेरी नमूना

LEFT JOIN bookings  
    ON rooms.id = bookings.room_type_id
    AND (bookings.arrival = ?
        OR bookings.departure = ?)

लारवेल कई शर्तों के साथ जुड़ते हैं

->leftJoin('bookings', function($join) use ($param1, $param2) {
    $join->on('rooms.id', '=', 'bookings.room_type_id');
    $join->on(function($query) use ($param1, $param2) {
        $query->on('bookings.arrival', '=', $param1);
        $query->orOn('departure', '=',$param2);
    });
})

11

मैं laravel5.2 का उपयोग कर रहा हूं और हम विभिन्न विकल्पों के साथ जोड़ सकते हैं, आप अपनी आवश्यकता के अनुसार संशोधित कर सकते हैं।

Option 1:    
    DB::table('users')
            ->join('contacts', function ($join) {
                $join->on('users.id', '=', 'contacts.user_id')->orOn(...);//you add more joins here
            })// and you add more joins here
        ->get();

Option 2:
    $users = DB::table('users')
        ->join('contacts', 'users.id', '=', 'contacts.user_id')
        ->join('orders', 'users.id', '=', 'orders.user_id')// you may add more joins
        ->select('users.*', 'contacts.phone', 'orders.price')
        ->get();

option 3:
    $users = DB::table('users')
        ->leftJoin('posts', 'users.id', '=', 'posts.user_id')
        ->leftJoin('...', '...', '...', '...')// you may add more joins
        ->get();

3

के बीच कच्चे प्रश्नों और मानक चयन के बीच एक अंतर (नहीं है DB::rawऔरDB::select विधियों के ) में ।

आप वही कर सकते हैं जो आप प्लेसहोल्डर DB::selectमें इस्तेमाल करना चाहते हैं और ?जैसे आप तैयार किए गए स्टेटमेंट्स के साथ करते हैं (यह वास्तव में यह क्या कर रहा है)।

एक छोटा सा उदाहरण:

$results = DB::select('SELECT * FROM user WHERE username=?', ['jason']);

दूसरा पैरामीटर मानों की एक सरणी है जिसका उपयोग क्वेरी में बाएं से दाएं प्लेसहोल्डर्स को बदलने के लिए किया जाएगा।


क्या इसका मतलब यह है कि पैरामीटर स्वचालित रूप से बच जाते हैं (SQL इंजेक्शन से बचाएं)?
देदे

2
हां, यह पीडीओ तैयार बयानों के लिए सिर्फ एक आवरण है।
जेसन लुईस

क्या लेफ्ट जॉइन में उस तकनीक को ऑन क्लॉज में इस्तेमाल करने का कोई तरीका है? मेरा प्रश्न यहाँ देखें । मैंने अपने बाएँजोन बंद करने की कोशिश की $join->on('winners.year','=',DB::select('?',array('2013'));लेकिन काम नहीं किया।
प्राग्रामर

यह वास्तव में कैसे वाक्पटु संचालित करने के लिए डिज़ाइन नहीं किया गया है। आप बस एक DB :: रॉ () कर सकते हैं और इसे स्वयं बना सकते हैं
mydoglixu
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.