Многочисленные союзы Laravel

У меня возникла проблема с добавлением запроса с несколькими Unions «laravel way».

Я пытаюсь выполнить запрос, эквивалентный тому, который создается следующим образом:

$ipsql = ""; for ($n = 1; $n < $total_networks; $n++) { $ipsql .= "(SELECT * FROM ip WHERE network = " . $n . " AND used = 0 LIMIT 5) UNION ALL"; } if ($n == $total_networks) { $ipsql .= "(SELECT * FROM ip WHERE network = " . $n . " AND used = 0 LIMIT 3) ORDER BY ip_addr"; } 

Я не нашел вариант для объединений с Eloquent, поэтому я пытался использовать построитель запросов для этого конкретного раздела, но я все время сталкиваюсь с проблемой при использовании сборщиков unionAll.

Используя это:

 $ip_list = DB::table('ips')->where('network', '=', '0')->where('used', '=', '0')->limit(5); for($n = 1; $n < $network_count; $n++){ $ip_list = DB::table('ips')->where('network', '=', $n)->where('used', '=', '0')->limit(5)->unionAll($ip_list); } $ips = $ip_list->get(); 

Я продолжаю получать синтаксическую ошибку MySQL:

  SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'union all ((select * from `ips` where `network` = ? and `used` = ? limit 5) unio' at line 1 (SQL: (select * from `ips` where `network` = 16 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 15 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 14 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 13 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 12 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 11 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 10 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 9 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 8 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 7 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 6 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 5 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 4 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 3 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 2 and `used` = 0 limit 5) union all ((select * from `ips` where `network` = 1 and `used` = 0 limit 5) union all (select * from `ips` where `network` = 0 and `used` = 0 limit 5))))))))))))))))) 

Я вижу из ошибки, что его вложение каждого нового объединения, который создает проблему синтаксиса. Я пробовал выполнить ту же задачу с DB :: raw, но, похоже, это тоже что-то похожее. Есть ли способ достичь этого, который лучше подходит для laravel? Спасибо, что посмотрели!

Ваши вызовы unionAll действительно становятся вложенными. Одним из решений является создание подзапроса в цикле for , а затем unionAll который подзапросит основной запрос после его определения. Затем вы бежите, когда вы закончите, на всякий шебанг, вот так:

 $ips_list = DB::table('ips')->where('network', '=', '1')->where('used', '=', '0')->limit(5); for($n = 1; $n < $total_networks; $n++){ $ip_list_subquery = DB::table('ips') ->where('network', '=', $n) ->where('used', '=', '0') ->limit(5); $ips_list = $ips_list->unionAll($ip_list_subquery); } $ips = $ips_list->get(); 

Итак, эффективно, вы unionAll звонки:

$a->unionAll($b)->unionAll($c)->unionAll($d)...

а не вложенных в них:

$a->unionAll($b->unionAll($c->unionAll($d...))))

// Использовать PDO. Это самый простой ответ, который я нашел после двух дней борьбы за использование сложного UNION в Laravel

  $PDO = DB::connection('mysql')->getPdo(); $billingStmt = $PDO->prepare(" select * from (SELECT * FROM t_statements WHERE reference_id = $user_id AND service_provider='FOLDER' AND bill_name IS NOT NULL ORDER BY bill_name ASC ) AS a UNION ALL SELECT * FROM ( SELECT * FROM t_statements WHERE reference_id = $user_id AND service_provider !='FOLDER' AND bill_name IS NOT NULL ORDER BY (CASE WHEN is_paid = 0 THEN due_date ELSE is_paid END) DESC) b "); $billingStmt->execute(); $usersBills = $billingStmt->fetchAll((\PDO::FETCH_ASSOC)); header('Content-Type: application/json'); $androidUserBills = json_encode($usersBills); // return results as json return response($androidUserBills); 

// Ответ JSON

  [ { "id": "247", "created_at": "2016-02-23 10:44:33", "updated_at": "2016-02-23 16:58:57", "t_user_account_id": "245", "statement_date": null, "due_date": "0000-00-00 00:00:00", "amount": "0", "is_paid": "0", "is_reminded": "1", "overdue": null, "current_amount": null, "bill_total": "88.5", "bill_id": "zd91NwGU", "bill_name": "Utility", "predecessor": null, "reference_id": "120", "service_provider": "FOLDER", "sp_id": null }, { "id": "252", "created_at": "2016-02-23 16:29:50", "updated_at": "2016-02-23 16:58:25", "t_user_account_id": "250", "statement_date": null, "due_date": "2016-03-04 17:52:34", "amount": "0", "is_paid": "0", "is_reminded": "1", "overdue": null, "current_amount": null, "bill_total": "88.5", "bill_id": "Lojnc", "bill_name": "Water bill", "predecessor": null, "reference_id": "120", "service_provider": "IWK", "sp_id": "7" } ] 

Это работает, но это слишком много. Вы можете просто использовать DB :: select («ANY RAW Query»);