Как обновить данные в mysql через каждые три записи?

Dima83

Новичок
У меня есть две таблицы.
1. attachment – там содержится 15 записей
2. download – статьи – 600 записей.
В download есть поле id_pos, это поле нужно обновить и добавить содержимое id 15 записей из другой таблицы attachment.
PHP:
<?php
include "config.php";

?>
<script src="https://mysite5.su/js/jquery-1.9.1.js"></script>
<link rel="StyleSheet" type="text/css" href="style.css">
<?php
//Подсчет attachment, чтобы знать сколько записей
function count_attach()
{
  global $dbh;
  $query = "SELECT * FROM attachment";
  $STH = $dbh->prepare($query);
  $STH->execute();
 
  $item = $STH->fetch(PDO::FETCH_ASSOC);
  $count_attach = $STH->rowCount();
 
  return $count_attach;
}
      
      //Выбираем все записи из attachment
      try {
           $query = "SELECT * FROM attachment";
           $STH = $dbh->prepare($query);
           $STH->execute();
          
           $items = $STH->fetchAll(PDO::FETCH_ASSOC);
           $STH = $dbh->prepare($query);
           $STH->execute();
           $count = count_attach();
          }
          catch(PDOException $e) {
            echo "Обнаружена ошибка. Напишите администратору. $email<br>"; 
            file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
          }
      //Выбираем записи из download, эквивалентно количеству записей в attachment
      try {
         $query = "SELECT * FROM download ORDER BY ID LIMIT $count";
         $STH = $dbh->prepare($query);
         $STH->execute();
        
      
          $news = $STH->fetchAll();
       //Обновляем id_pos (по порядку), по id которое прописано в условии
          $STH = $dbh->prepare("UPDATE download SET id_pos = ? WHERE id = ?");
          foreach ( $news as $key=>$n ) {
            
             $STH->execute(array($items[$key]["id"], $n["id"]));
          }
      }
        catch(PDOException $e) {
          echo "Обнаружена ошибка. Напишите администратору. $email<br>"; 
          file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
       }
?>
Как сделать обновление id_pos в download только не каждую запись, а предположим с интервалом в 3, 4 или 5 записей?
 

WMix

герр M:)ller
Партнер клуба
чтоб у тебя не было иллюзий, открою тайну, мы не даем ответы на вопросы, а обсуждаем подход

для начала, я посоветовал бы тебе немного окунуться в язык sql.

к примеру этот кусок
PHP:
function count_attach()
{
  global $dbh;
  $query = "SELECT * FROM attachment";
  $STH = $dbh->prepare($query);
  $STH->execute();

  $item = $STH->fetch(PDO::FETCH_ASSOC);
  $count_attach = $STH->rowCount();

  return $count_attach;
}
обычно решается так
SQL:
SELECT count(*) FROM attachment
а весь скрипт (задача) просто наверняка решается одним UPDATE запросом.
я если честно по скрипту так и не понял что ты обновляешь, вернее не понял логическую последовательность, там обновятся случайные 15 записей вроде

покажи структуры и опиши словами что и где нужно обновить
 

Dima83

Новичок
WMix, Вот пример моих таблиц.
1604

1.attachment – пункт 1 на картинке
2.download (пункт 2 на картинке) – с помощью запросов которые я привел в посте номер 1 происходит перенос id из attachment в таблицу 2 id_pos.
3.Как сделать интервал перед обновлением, чтобы через каждые три записи происходило обновление, а пропущенные поля оставались без изменения (т.е. нули). Пример итогового результата на картинке под пунктом 3 (изменил в ручную для примера).
 

WMix

герр M:)ller
Партнер клуба
2.download (пункт 2 на картинке) – с помощью запросов которые я привел в посте номер 1 происходит перенос id из attachment в таблицу 2 id_pos.
а по какому принципу, допустим первая запись в attachment = 1, в какую из строк download она должна попасть
 

Dima83

Новичок
а по какому принципу, допустим первая запись в attachment = 1, в какую из строк download она должна попасть
Начиная с первой позиции download и дальше каждые три пропускать и обновлять.
 

WMix

герр M:)ller
Партнер клуба
ну смотри, тебе нужна опорная последовательность, на id опираться по хорошему нельзя
те тебе ее нужно сгенерить


решается с помощью join самой себя (test замени на download или attachment, а id на поле сортировки)
SQL:
SELECT t1.*, count(t2.id)+1 as nr
  FROM test t1

  LEFT
  JOIN test t2
    ON t2.id < t1.id

GROUP
    BY t1.id
если опорная последовательность готова, то каждая 4я запись начиная с первой будет

SQL:
SELECT t3.*
  FROM (
    SELECT t1.*, count(t2.id)+1 as nr
      FROM test t1
      LEFT
      JOIN test t2
        ON t2.id < t1.id
    GROUP
        BY t1.id
  ) as t3
WHERE nr%4=1;
ну а остальное update
 
Последнее редактирование:

Dima83

Новичок
Для чего нужен первый запрос? Я просто подставил второй запрос вместо своего и заработало, правда на обработку требуется много ресурсов. Приходится ждать пока запрос пройдет по всем полям.
PHP:
<?php
include "config.php";
echo time();
?>
<script src="https://mysite5.su/js/jquery-1.9.1.js"></script>
<link rel="StyleSheet" type="text/css" href="style.css">
<?php
    //Выбираем все записи из attachment
      try {
           $query = "SELECT * FROM attachment";
           $STH = $dbh->prepare($query);
           $STH->execute();
        
           $items = $STH->fetchAll(PDO::FETCH_ASSOC);
           $STH = $dbh->prepare($query);
           $STH->execute();
           
          }
          catch(PDOException $e) {
            echo "Обнаружена ошибка. Напишите администратору. $email<br>";
            file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
          }
     
      try {
         $query = "SELECT t3.*
              FROM (
                SELECT t1.*, count(t2.id)+1 as nr
                  FROM download t1
                  LEFT
                  JOIN download t2
                    ON t2.id < t1.id
                GROUP
                    BY t1.id
              ) as t3
            WHERE nr%4=1;";
         $STH = $dbh->prepare($query);
         $STH->execute();
      
    
          $news = $STH->fetchAll();
       //Обновляем id_pos (по порядку), по id которое прописано в условии
          $STH = $dbh->prepare("UPDATE download SET id_pos = ? WHERE id = ?");
          foreach ( $news as $key=>$n ) {
             // echo $n["id"]."<br>";
             $STH->execute(array($items[$key]["id"], $n["id"]));
          }
      }
        catch(PDOException $e) {
          echo "Обнаружена ошибка. Напишите администратору. $email<br>";
          file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
       }
?>
 

WMix

герр M:)ller
Партнер клуба
Для чего нужен первый запрос?
для понимания
правда на обработку требуется много ресурсов.
он сложный запрос, но для ~1000 записей должен и без индекса хорошо работать, иначе смотри explain

я конечно предлагал тебе включить голову и переписать select в update и обойтись без php
 

Dima83

Новичок
Здравствуйте, нужно заполнить данные до конца таблицы download собирая данные из таблицы attachment, т.е. 15 записей обновить в download, потом еще 15 и так до конца download. Решил сделать вот так.
PHP:
<?php
include "config.php";

?>
<script src="https://mysite5.su/js/jquery-1.9.1.js"></script>
<link rel="StyleSheet" type="text/css" href="style.css">
<?php
    //Выбираем все записи из attachment
      try {
           $query = "SELECT * FROM attachment";
           $STH = $dbh->prepare($query);
           $STH->execute();
      
           $items = $STH->fetchAll(PDO::FETCH_ASSOC);
           $count_atch = $STH->rowCount();
           $STH = $dbh->prepare($query);
           $STH->execute();
        
          }
          catch(PDOException $e) {
            echo "Обнаружена ошибка. Напишите администратору. $email<br>";
            file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
          }
  
      try {
         $query = "SELECT * FROM download";
         $STH = $dbh->prepare($query);
         $STH->execute();
    
  
          $news = $STH->fetchAll();
          $count = $STH->rowCount();
          echo "<br>".$count."<br>".$count_atch;
        
          $m=0;
       //Обновляем id_pos (по порядку), по id которое прописано в условии
          $STH = $dbh->prepare("UPDATE download SET id_pos = ? WHERE id = ?");
          $data1 = [];
      
          //UPDATE `download` SET`id_pos`=0
          echo "<br><br>";
          $test1 = 0;
      
          foreach ( $news as $key=>$n ) {
          
             $data1[$key] = $items[$key]["id"];
          
          
          
             if ($key % 4 == 1 && $m<=$count_atch)
             {
                $test1 = $data1[$m];
            
               //  echo $n["id"]."<br>";
                $STH->execute(array($data1[$m], $n["id"]));
                $m++;
                if ($m >= $count_atch)
                {
                  $m = 0;
                }
              
             }
             else $test1 = 0;
             //Проверка
             echo $test1."<br>";
          
          
          
          }
      }
        catch(PDOException $e) {
          echo "Обнаружена ошибка. Напишите администратору. $email<br>";
          file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
       }
?>
Происходит следующее.
  1. Начинается не с первой записи, а со второй. Т.е. первая 0, вторая id_pos=1
  2. Пропуск происходит вначале на два поля, хотя я поставил значение 3, следующий пропуск 4 поля и только. потом пропуски идут по 3.
img1.jpg
В чем тут может быть проблема?
 

WMix

герр M:)ller
Партнер клуба
в SELECT * FROM attachment добавь order by
$key % 4 == 1 - каждая 4 начиная с 1 (не нулевой)
остальное не читал
 
Сверху