লারাভেল কোয়েরি বিল্ডার ব্যবহার করে সাবকিয়ারি থেকে কীভাবে নির্বাচন করবেন?


104

আমি নিম্নলিখিত এসকিউএল দ্বারা এলওভারেন্ট ওআরএম ব্যবহার করে মান পেতে চাই।

- এসকিউএল

 SELECT COUNT(*) FROM 
 (SELECT * FROM abc GROUP BY col1) AS a;

তারপর আমি নিম্নলিখিত বিবেচনা।

- কোড

 $sql = Abc::from('abc AS a')->groupBy('col1')->toSql();
 $num = Abc::from(\DB::raw($sql))->count();
 print $num;

আমি আরও ভাল সমাধান খুঁজছি

সহজ সমাধান আমাকে বলুন।

উত্তর:


136

@ ডেলমর্ডারের উত্তর এবং আপনার মন্তব্যগুলি ছাড়াও:

বর্তমানে FROMঅনুচ্ছেদে সাবকিউরি তৈরির কোনও পদ্ধতি নেই , সুতরাং আপনাকে ম্যানুয়ালি কাঁচা বিবৃতি ব্যবহার করতে হবে, প্রয়োজনে, আপনাকে সমস্ত বাইন্ডিংগুলি মার্জ করতে হবে:

$sub = Abc::where(..)->groupBy(..); // Eloquent Builder instance

$count = DB::table( DB::raw("({$sub->toSql()}) as sub") )
    ->mergeBindings($sub->getQuery()) // you need to get underlying Query Builder
    ->count();

মনে রাখবেন যে আপনাকে সঠিক ক্রমে বাইন্ডিংগুলি মার্জ করতে হবে । আপনার যদি অন্য আবদ্ধ অনুচ্ছেদগুলি থাকে তবে আপনার অবশ্যই এটি পরে রাখা উচিত mergeBindings:

$count = DB::table( DB::raw("({$sub->toSql()}) as sub") )

    // ->where(..) wrong

    ->mergeBindings($sub->getQuery()) // you need to get underlying Query Builder

    // ->where(..) correct

    ->count();

4
নোট করুন যে আপনার belongsToManyসাবলেট হিসাবে জটিল প্রশ্ন থাকলে আপনাকে getQuery()দুবার যোগ করতে হবে =>$sub->getQuery()->getQuery()
জর্ডি পুইগডেলভোল

4
@ স্কাইজার আপনি যা লিখছেন তা আপনি পড়ছেন না। আপনি কল করলে কিছুই পালানো যায় না toSql। পিডিও পিএইচপিএন / ম্যানুয়াল /en/book.pdo.php সম্পর্কে পড়ুন এবং আপনার ফলাফল দেখুন$query->toSql()
জারেক টাকাসেক

4
সঙ্গে শুভেচ্ছা করতে -> mergeBindings ($ উপ-> getQuery ()) শুধু কি -> mergeBindings ($ সাব)
জিমি Ilenloa

4
@ জিমিআইলেনোোয়া যদি $subক্যোয়ারী একজন প্রচ্ছন্ন নির্মাতা হয় তবে আপনার এখনও ->getQuery()অংশটি প্রয়োজন , অন্যথায় আপনি ত্রুটি পান কারণ এই পদ্ধতিটি Query\Builderক্লাসের বিরুদ্ধে টাইপ করা হয়েছে ।
জারেক টাকাসেক

4
@ ক্যানান না এটি আমার অনুমান মতো একজন PR এর প্রার্থী, তবে শেষ পর্যন্ত এটি খুব সাধারণ ব্যবহারের ক্ষেত্রে নয়। সম্ভবত আজ অবধি সেখানে এটি না থাকার কারণ ..
জারেক টাকাসেক

82

লারাভেল ভি 5.6.12 (2018-03-14) বিল্ডারকে জিজ্ঞাসা করার পদ্ধতি fromSub()এবং fromRaw()পদ্ধতি (# 23476)

গৃহীত উত্তর সঠিক তবে এটিকে সরলীকৃত করা যেতে পারে:

DB::query()->fromSub(function ($query) {
    $query->from('abc')->groupBy('col1');
}, 'a')->count();

উপরের স্নিপেটটি নিম্নলিখিত এসকিউএল উত্পাদন করে:

select count(*) as aggregate from (select * from `abc` group by `col1`) as `a`

16

@ জেরেকটাক্যাসিকের সমাধানটি হ'ল আমি যা খুঁজছিলাম। আপনি যখন DB::table()প্রশ্নগুলি ব্যবহার করছেন তখন এটি কীভাবে করা যায় তা কেবলমাত্র আমি মিস করি । এই ক্ষেত্রে, আমি এটি এটি করি:

$other = DB::table( DB::raw("({$sub->toSql()}) as sub") )->select(
    'something', 
    DB::raw('sum( qty ) as qty'), 
    'foo', 
    'bar'
);
$other->mergeBindings( $sub );
$other->groupBy('something');
$other->groupBy('foo');
$other->groupBy('bar');
print $other->toSql();
$other->get();

পদ্ধতিটি mergeBindingsব্যবহার না করে কীভাবে তৈরি করা যায় সে সম্পর্কে বিশেষ মনোযোগ দিনgetQuery()


ব্যবহার DB::raw()আমার জন্য কাজটি করেছে
নিনো Škopac

7

লারাভেল ৫.৫ থেকে সাবকিউরিয়ের জন্য একটি উত্সর্গীকৃত পদ্ধতি রয়েছে এবং আপনি এটি এটি ব্যবহার করতে পারেন:

Abc::selectSub(function($q) {
    $q->select('*')->groupBy('col1');
}, 'a')->count('a.*');

বা

Abc::selectSub(Abc::select('*')->groupBy('col1'), 'a')->count('a.*');

4
দেখে মনে হচ্ছে সাব-ইলেক্ট্রেট কেবল কেবল নির্বাচন থেকে সাব-কোয়েরি যুক্ত করতে ব্যবহৃত হতে পারে, না FROM।
হাজাবাকা

4
Call to undefined method subSelect()মনে হচ্ছে subSelectঅস্তিত্ব নেই।
মারুফ আলোম

4
এটি আমার নজরে আনার জন্য ধন্যবাদ, আমি নামটি ভুল বানাই, এটি হওয়া উচিত ছিল selectSub। আমি এখন আমার প্রতিক্রিয়া আপডেট করেছি।
সাসা ব্লগোজেভিক

3

আমি এই জাতীয় কিছু করতে পছন্দ করি:

Message::select('*')
->from(DB::raw("( SELECT * FROM `messages`
                  WHERE `to_id` = ".Auth::id()." AND `isseen` = 0
                  GROUP BY `from_id` asc) as `sub`"))
->count();

এটি খুব মার্জিত নয়, তবে এটি সহজ।


ধন্যবাদ এটি আমার পক্ষে কাজ করেছে, পার্শ্ব নোট হিসাবে, নির্বাচিত সামগ্রীটি সম্পর্কে সতর্কতা অবলম্বন করুন কারণ লারাভেল কিছু উদ্ধৃতি চিহ্ন যুক্ত করেছে এবং এগুলি থেকে মুক্তি পাওয়ার জন্য আমাকে>> নির্বাচন (\ ডিবি :: কাঁচা ('আপনার নির্বাচন')) ব্যবহার করতে হয়েছিল।
ওয়াক

2

আমি আপনার কোডটি কাঙ্ক্ষিত ক্যোয়ারীটি করতে করতে পারিনি, এএসটি কেবলমাত্র টেবিলের জন্য একটি উপাধি abc, উত্পন্ন টেবিলের জন্য নয়। লারাভেল ক্যোয়ারী বিল্ডার স্পষ্টতই উত্পন্ন টেবিল উপকরণগুলি সমর্থন করে না, ডিবি :: কাঁচা সম্ভবত এর জন্য প্রয়োজন।

আমি যে সরাসরি সমাধানটি নিয়ে আসতে পেরেছি তা প্রায় আপনার মতোই, তবে আপনি যেমন জিজ্ঞাসা করেছিলেন তেমনই ক্যোয়ারী তৈরি করে:

$sql = Abc::groupBy('col1')->toSql();
$count = DB::table(DB::raw("($sql) AS a"))->count();

উত্পাদিত ক্যোয়ারী হয়

select count(*) as aggregate from (select * from `abc` group by `col1`) AS a;

ধন্যবাদ তোমার উত্তরের জন্য. "অ্যাবসি :: থেকে (???) এবং ডিবি :: টেবিল (???)" পদ্ধতিতে সমস্যা আছে। $ sql = Abc :: where ('id', '=', $ id) -> groupBy ('col1') -> toSQL (); $ গণনা = ডিবি :: টেবিল (ডিবি :: কাঁচা ("($ বর্গক্ষেত্র) এএস" ")) -> গণনা (); উপরের কোডে এসকিউএল ত্রুটি ঘটে। - কোথায় এবং পরামিতি বরাদ্দ!
quenty658

2

এই উত্তরে বর্ণিত সঠিক উপায়: https://stackoverflow.com/a/52772444/2519714 বর্তমান মুহুর্তে সর্বাধিক জনপ্রিয় উত্তর সম্পূর্ণ সঠিক নয়।

এই ভাবে https://stackoverflow.com/a/24838367/2519714 কিছু ক্ষেত্রে সঠিক নয় যেমন: সাব-সিলেক্টের যেখানে বাইন্ডিং রয়েছে, তারপরে সাব-সিলেক্ট করতে সারণিতে যোগদান করা হবে, তারপরে অন্যান্য চাকাগুলি সমস্ত প্রশ্নের সাথে যুক্ত হয়েছে। উদাহরণস্বরূপ ক্যোয়ারী: select * from (select * from t1 where col1 = ?) join t2 on col1 = col2 and col3 = ? where t2.col4 = ? এই ক্যোয়ারীটি তৈরি করতে আপনি কোড লিখবেন:

$subQuery = DB::query()->from('t1')->where('t1.col1', 'val1');
$query = DB::query()->from(DB::raw('('. $subQuery->toSql() . ') AS subquery'))
    ->mergeBindings($subQuery->getBindings());
$query->join('t2', function(JoinClause $join) {
    $join->on('subquery.col1', 't2.col2');
    $join->where('t2.col3', 'val3');
})->where('t2.col4', 'val4');

এই কোয়েরিটি সম্পাদন করার সময়, তার পদ্ধতিটি উল্লিখিত কাঁচা এসকিএল এর পরিবর্তে এই ক্ষেত্রে $query->getBindings()যেমন ভুল ক্রমে বাইন্ডিংগুলি ফিরিয়ে দেবে ।['val3', 'val1', 'val4']['val1', 'val3', 'val4']

এটি করার জন্য আরও একটি সময় সঠিক উপায়:

$subQuery = DB::query()->from('t1')->where('t1.col1', 'val1');
$query = DB::query()->fromSub($subQuery, 'subquery');
$query->join('t2', function(JoinClause $join) {
    $join->on('subquery.col1', 't2.col2');
    $join->where('t2.col3', 'val3');
})->where('t2.col4', 'val4');

এছাড়াও বাইন্ডিংগুলি স্বয়ংক্রিয়ভাবে এবং সঠিকভাবে নতুন ক্যোয়ারিতে মার্জ হবে।


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