Как мне упростить и ускорить 3 запроса, каждый из которых основан на следующем?

#php #mysql #pdo

#php #mysql — сервер #pdo ( пдо )

Вопрос:

Несколько лет назад я создал простую систему t-card для работы, и с тех пор она работает по назначению (обрабатывает около 300 заданий), сейчас она далека от совершенства, и поэтому, учитывая рост рабочей нагрузки за последние несколько месяцев из-за пандемии (обрабатывает около 2000 заданий), время загрузки значительно замедлилось с 30 секунд (в любом случае, не очень большое) до иногда 10 минут или просто истекает время ожидания.

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

                             $getdates = $conn->prepare("SELECT delivery_date FROM orders INNER JOIN stages ON orders.id = stages.order_id WHERE isnull(stages.stage_8_name)  GROUP BY delivery_date");
                            $getdates->execute();

                            if($getdates->rowCount()) {

                                foreach ($getdates->fetchAll(PDO::FETCH_ASSOC) as $row) {                                          

                                    $delivery_date = $row['delivery_date'];
                                    
                                    $getdates_c = $conn->prepare("SELECT delivery_date FROM orders INNER JOIN stages ON orders.id = stages.order_id WHERE isnull(stages.stage_8_name) AND delivery_date = :delivery_date  ");
                                    $getdates_c->execute(array(':delivery_date' => $delivery_date));


                                    $number_of_cards = $getdates_c->rowCount();  
  

При этом будет получена дата для всех заданий, которые еще предстоит выполнить. Затем я создаю заголовок таблицы с каждой датой и количеством заданий на эту дату. Затем я проверяю, какие Драйверы недоступны в этот день с помощью:

 $getstaff = $conn->prepare("SELECT * FROM staff WHERE position = 4 ORDER BY name asc");
                        $getstaff->execute();
                            foreach ($getstaff->fetchAll(PDO::FETCH_ASSOC) as $row) { 
                                $staff_id = $row['id']; 

                            $gethol = $conn->prepare("SELECT * FROM staff_holiday WHERE staff_id = :staff_id AND day = :holday AND (type = 'Holiday' OR type = 'Holiday Half')");
                            $gethol->execute(array(':staff_id' => $staff_id, ':holday' => $delivery_date));

                                foreach ($gethol->fetchAll(PDO::FETCH_ASSOC) as $row) { 
                                    $type_hol = $row['type']; 
                                    $staff_id = $row['staff_id'];   
  

И добавьте это в заголовок таблицы.

Затем я в основном повторяю запрос даты для тела таблицы с:

 $getdates = $conn->prepare("SELECT delivery_date FROM orders INNER JOIN stages ON orders.id = stages.order_id WHERE isnull(stages.stage_8_name)  GROUP BY delivery_date");
                                $getdates->execute();

                                if($getdates->rowCount()) {

                                    foreach ($getdates->fetchAll(PDO::FETCH_ASSOC) as $row) {   
                                        $delivery_date = $row['delivery_date'];
  

а затем, используя эту дату, пройдите цикл по массиву фургонов и получите количество заданий на фургон и создайте заголовок вложенной таблицы с номером фургона и количеством заданий:

 $vans = array(0,1,2,3,4,5);

                                            foreach ($vans as $this_van) {

                                                $sql = "SELECT count(*) FROM `orders` INNER JOIN stages ON orders.id = stages.order_id WHERE isnull(stages.stage_8_name) AND orders.delivery_date = :delivery_date AND orders.van = :this_van "; 
                                                $result = $conn->prepare($sql); 
                                                $result->execute(array(':delivery_date' => $delivery_date,':this_van' => $this_van )); 
                                                $number_of_rows = $result->fetchColumn(); 
  

затем, наконец, я получаю все задания для каждого фургона на этот конкретный день и перечисляю их в порядке выполнения:

 $getproduction = $conn->prepare("SELECT orders.about 20 different fields, stages.another 20 fields FROM orders INNER JOIN stages ON orders.id = stages.order_id WHERE isnull(stages.stage_8_name) AND orders.delivery_date = :delivery_date AND orders.van = :this_van  ORDER BY drop_no ASC");
                                                $getproduction->bindParam(':delivery_date', $delivery_date);
                                                $getproduction->bindParam(':this_van', $this_van);
                                                $getproduction->execute();
                                                    foreach ($getproduction->fetchAll(PDO::FETCH_ASSOC) as $row) {  
                                                        $order_id = $row['id']; 
  

итак, здесь перечислены все сведения об этой работе.

В итоге я получаю список дат с номерами фургонов ниже и рабочих мест, перечисленных под номерами фургонов.Образец Tcards

Любая помощь в упрощении этого или просто ускорении его выполнения была бы замечательной. Спасибо.

РЕДАКТИРОВАТЬ: Хорошо, основываясь на ваших комментариях, я сократил все до тестирования и пока получил это:

 // Gets all orders and sorts by drop number
    $getorders = $conn->prepare("SELECT * FROM orders INNER JOIN customers ON orders.customer_id = customers.customer_id INNER JOIN addresses on orders.address_id = addresses.address_id ORDER BY drop_no");
    $getorders->execute();

    $result = $getorders->fetchAll(PDO::FETCH_ASSOC);

// groups order by date, van, drop
    foreach ( $result as $value ) {
        $group[$value['delivery_date']][$value['van_no']][$value['drop_no']][] = $value;
    }

// outputs orders by date -> van -> drop

    var_dump($group);
  

вот так:

 array (size=2)
  '2020-08-25' => 
    array (size=2)
      1 => 
        array (size=3)
          0 => 
            array (size=8)
              'orders_id' => string '6' (length=1)
              'customer_id' => string '1' (length=1)
              'address_id' => string '1' (length=1)
              'van_no' => string '1' (length=1)
              'drop_no' => string '0' (length=1)
              'delivery_date' => string '2020-08-25' (length=10)
              'customer_name' => string 'One' (length=3)
              'address_postcode' => string 'b1' (length=2)
          1 => 
            array (size=8)
              'orders_id' => string '1' (length=1)
              'customer_id' => string '1' (length=1)
              'address_id' => string '1' (length=1)
              'van_no' => string '1' (length=1)
              'drop_no' => string '1' (length=1)
              'delivery_date' => string '2020-08-25' (length=10)
              'customer_name' => string 'One' (length=3)
              'address_postcode' => string 'b1' (length=2)
  

Любая помощь в том, как я бы напечатал заголовок delivery_date, а затем подзаголовок van_no со всеми заданиями, напечатанными под их van_no в порядке drop_no? все, что я использую для эхо-вывода, повторяет дату и значение van для каждого задания.

Еще раз спасибо.

Комментарии:

1. 1) 2-й запрос в 1-м фрагменте кода кажется бессмысленным. У вас уже есть эта информация из 1-го запроса. 2) если у вас есть цикл foreach, основанный на результате запроса, в котором вы выдаете другой запрос, то вы в основном реализовали объединение базы данных в php. Выполните объединение в базе данных. 3) повторять один и тот же запрос снова и снова — пустая трата времени и ресурсов. Просто сохраните результаты в массиве, чтобы повторно использовать значения без повторения запроса.

2. ДА. Смотрите о соединениях (снова) и обратите внимание, что при отсутствии каких-либо агрегирующих функций предложение GROUP BY никогда не подходит.

3. @Strawberry в OP используется group by вместо distinct, так что с oart все в порядке. Хотя добавление count(*) может помочь в случае с первым фрагментом кода.

4. @Shadow Эта часть не в порядке!