Вызов ROW из второго оператора - mysqli_multi_query [duplicate]

select * from yourtable
group by id
having rev=max(rev);
10
задан Harry Weinert 12 January 2011 в 11:18
поделиться

6 ответов

Хорошо, после некоторых попыток, проб и ошибок и получения ссылки с другого сообщения, которое я обнаружил в поиске Google, мне удалось решить мою проблему!

Вот новый код:

<?php

    $link = mysqli_connect("server", "user", "pass", "db");

    if (mysqli_connect_errno()) {
        printf("Connect failed: %s\n", mysqli_connect_error());
        exit();
    }

    $agentsquery = "CREATE TEMPORARY TABLE LeaderBoard (
        `agent_name` varchar(20) NOT NULL,
        `job_number` int(5) NOT NULL,
        `job_value` decimal(3,1) NOT NULL,
        `points_value` decimal(8,2) NOT NULL
    );";
    $agentsquery .= "INSERT INTO LeaderBoard (`agent_name`, `job_number`, `job_value`, `points_value`) SELECT agent_name, job_number, job_value, points_value FROM jobs WHERE YEAR(booked_date) = $current_year && WEEKOFYEAR(booked_date) = $weeknum;";
    $agentsquery .= "INSERT INTO LeaderBoard (`agent_name`) SELECT DISTINCT agent_name FROM apps WHERE YEAR(booked_date) = $current_year && WEEKOFYEAR(booked_date) = $weeknum;";
    $agentsquery .= "SELECT agent_name, SUM(job_value), SUM(points_value) FROM leaderboard GROUP BY agent_name ORDER BY SUM(points_value) DESC";

    mysqli_multi_query($link, $agentsquery) or die("MySQL Error: " . mysqli_error($link) . "<hr>\nQuery: $agentsquery");
    mysqli_next_result($link);
    mysqli_next_result($link);
    mysqli_next_result($link);

    if ($result = mysqli_store_result($link)) {
        $i = 0;
        while ($row = mysqli_fetch_array($result)){
            $number_of_apps = getAgentAppsWeek($row['agent_name'],$weeknum,$current_year);
            $i++;
?>

            <tr class="tr<?php echo ($i & 1) ?>">
                <td style="font-weight: bold;"><?php echo $row['agent_name'] ?></td>
                <td><?php echo $row['SUM(job_value)'] ?></td>
                <td><?php echo $row['SUM(points_value)'] ?></td>
                <td><?php echo $number_of_apps; ?></td>
            </tr>

<?php

        }
    }
?>

после того, как вы наложили mysqli_next_result в несколько раз для каждого запроса, он волшебным образом работал! ура! Я понимаю, почему он работает, потому что я говорю ему, чтобы перейти к следующему результату 3 раза, поэтому он пропускает результат для запроса № 4, который я хочу использовать.

Кажется немного но мне кажется, что это не так, как будто мне нужна команда для чего-то вроде mysqli_last_result ($ link) или что-то, если вы спросите меня ...

Спасибо за помощь rik и f00, я получил там в конце концов:)

3
ответ дан Harry Weinert 5 September 2018 в 10:42
поделиться

Я бы упростил то, что вы пытаетесь сделать, создав хранимая процедура, которая создаст статистику лидера / агента, а затем просто вызовет ее из вашего php (одного вызова) следующим образом:

полный скрипт здесь: http://pastie.org/1451802

, альтернативно, вы могли бы объединить ваши отдельные запросы в один оператор select / group by.

см. здесь: http://pastie.org/1451842

select
 leaders.agent_name, 
 sum(leaders.job_value) as sum_job_value, 
 sum(leaders.points_value) as sum_points_value 
from
(
select 
 agent_name, 
 job_number, 
 job_value, 
 points_value 
from 
 jobs 
where 
 year(booked_date) = 2011 and weekofyear(booked_date) = 2
union all
select distinct
 agent_name,
 0,0,0
from
 apps
where 
 year(booked_date) = 2011 and weekofyear(booked_date) = 2
) leaders
group by
 agent_name 
order by sum_points_value desc;

Сохраненная процедура

drop procedure if exists list_leaders;

delimiter #
create procedure list_leaders
(
in p_year smallint unsigned,
in p_week tinyint unsigned
)
begin

  create temporary table tmp_leaders(
    agent_name varchar(20) not null,
    job_number int unsigned not null default 0, -- note the default values
    job_value decimal(3,1) not null default 0,
    points_value decimal(8,2) not null default 0
  )engine=memory;

  insert into tmp_leaders (agent_name, job_number, job_value, points_value) 
    select agent_name, job_number, job_value, points_value from jobs 
    where year(booked_date) = p_year and weekofyear(booked_date) = p_week;

  insert into tmp_leaders (agent_name) -- requires default values otherwise you will get nulls
    select distinct agent_name from apps
    where year(booked_date) = p_year and weekofyear(booked_date) = p_week;

  select 
    agent_name, 
    sum(job_value) as sum_job_value, 
    sum(points_value) as sum_points_value 
   from
    tmp_leaders
   group by
    agent_name order by sum_points_value desc;

  drop temporary table if exists tmp_leaders;

end#

delimiter ;

call list_leaders(year(curdate()), weekofyear(curdate()));

PHP-скрипт

<?php

ob_start(); 

try
{
    $db = new mysqli("localhost", "foo_dbo", "pass", "foo_db", 3306);

    if ($db->connect_errno) 
        throw new exception(sprintf("Could not connect: %s", $db->connect_error));

    $sqlCmd = "call list_leaders(2011, 2)";
    $result = $db->query($sqlCmd);

    if(!$result) throw new exception(sprintf("Invalid query : %s", $sqlCmd));

    if($db->affected_rows <= 0){
        echo "no leaders found !";
    }
    else{
        $leaders = $result->fetch_all(MYSQLI_ASSOC);
        foreach($leaders as $ldr){
            // do stuff
            echo $ldr["agent_name"], "<br/>";
        }
    }
}
catch(exception $ex)
{
    ob_clean(); 
    echo sprintf("zomg borked - %s", $ex->getMessage());
}

if(!$db->connect_errno) $db->close();
ob_end_flush();
?>

Теперь попробуй проще - надеюсь, что это поможет:)

1
ответ дан Jon Black 5 September 2018 в 10:42
поделиться

Я хотел бы привести в порядок принятое решение плаката, чтобы привести его в соответствие с тем, что я считаю лучшим.

  • В то время как несколько строк mysqli_next_result ($ link) дают результат, он выглядит немного хакерским. Поэтому я собираюсь создать DO-WHILE на их месте.
  • Решение rik, связанное с созданием функции mysqli_last_result ($ link), является излишним. Мое состояние WHILE достигнет того же эффекта. Кроме того, код rik смешивает процедурные и объектно-ориентированные стили, которых следует избегать.
  • Я не буду подпрыгивать между php и html.
  • Я просто настрою класс, чтобы переключить Маленький.
  • Я поставлю getAgentAppsWeek () непосредственно в строке, так как я не люблю создавать переменные, которые упоминаются только один раз; и потому, что Гарри Вайнерт неплохо поименовал эту функцию.
  • IMO это просто читать легче.
    if(mysqli_multi_query($link,$agentsquery)){
        do{
            if($result=mysqli_store_result($link)){ // ignore if no record set
                while($row=mysqli_fetch_array($result)){
                    echo "<tr class=\"tr",(++$i & 1),"\">";
                        echo "<td style=\"font-weight:bold;\">",$row['agent_name'],"</td>";
                        echo "<td>",$row['SUM(job_value)'],"</td>";
                        echo "<td>",$row['SUM(points_value)'],"</td>";
                        echo "<td>",getAgentAppsWeek($row['agent_name'],$weeknum,$current_year),"</td>";
                    echo "</tr>";
                }
                mysqli_free_result($result);
            }
        } while(mysqli_more_results($link) && mysqli_next_result($link));
    }
    if($error_mess=mysqli_error($link)){
        echo "<tr class=\"error\"><td colspan=\"4\">Error: $error_mess</td></tr>";
    }
    //if any query returns false, mysqli_multi_query will stop
    // and the individual query error to blame will be provided.
    
0
ответ дан mickmackusa 5 September 2018 в 10:42
поделиться
0
ответ дан n0nag0n 5 September 2018 в 10:42
поделиться

Из руководства : mysqli_multi_query() возвращает bool, указывающий на успех.

Чтобы получить набор результатов из первого запроса, вы можете использовать mysqli_use_result () или mysqli_store_result (). Все последующие результаты запроса могут быть обработаны с помощью mysqli_more_results () и mysqli_next_result ().

Вот функция, которая возвращает последний результат многопроцесса:

function mysqli_last_result($link) {
    while (mysqli_more_results($link)) {
        mysqli_use_result($link); 
        mysqli_next_result($link);
    }
    return mysqli_store_result($link);
}

Использование:

$link = mysqli_connect();

$query  = "SELECT 1;";
$query .= "SELECT 2;";
$query .= "SELECT 3";

mysqli_multi_query($link, $query);
$result = mysqli_last_result($link);
$row = $result->fetch_row();
echo $row[0];  // prints "3"

$result->free();
mysqli_close($link);
8
ответ дан rik 5 September 2018 в 10:42
поделиться

Сохранить результат в переменной и в конце использовать эту переменную.

    do{
        if($result = $con->store_result()){
            $data=$result->fetch_all();
            $result->free();
        }
    } while($con->more_results()&&$con->next_result());
    echo(json_encode($data));
1
ответ дан Vardan Aggarwal 5 September 2018 в 10:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: