Home » Php » sql – Correctly storing query response with GROUP BY using PHP

sql – Correctly storing query response with GROUP BY using PHP

Posted by: admin February 25, 2020 Leave a comment

Questions:

I have this big database storing a lot of info about customers and bills and so on. What I want to do is, using the id’s of the customers, search for all their bills, SUM() the price contained in every one of them, and store them to print one unique bill.

So I sarted thinking of this:

try {
    $conn = new PDO('mysql:host=myhost;dbname=accounting','user','pass');
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}catch(PDOException $e){
    echo "ERROR: " . $e->getMessage();
}



$stmt = $conn->prepare('SELECT GROUP_CONCAT(DISTINCT source_external_subscriber_id) AS ids 
                        FROM cdr');
$stmt->execute();
foreach ($stmt as $row) {
    $string = $row['ids'];
}

$array = explode(',', $string);
array_pop($array);
array_shift($array);


$destinationId = 0;
foreach ($array as $id) {
    $stmt2 = $conn->prepare('SELECT id, call_type, source_customer_cost 
                            FROM cdr 
                            WHERE source_external_subscriber_id = :id 
                            AND destination_account_id = :destinationId');

    $stmt2->execute(array('id' => $id, 'destinationId' => $destinationId));

    foreach ($stmt2 as $row2) {
        $datos[] = $row2;
    }
}

I was not convinced by the result so I decided to check for myself, executing my code first ad then looking for a customer to compare the number of bills to the lenght of the array (hence the lack of SUM() yet)
Then, as I was looking for a more convincing way I stumbled upon this really useful post. So I changed my code to this. But here they only explain how to write the query, not how to store it inside an array.

try {
    $conn = new PDO('mysql:host=host;dbname=accounting','user','pass');
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    var_dump($conn);
}catch(PDOException $e){
    echo "ERROR: " . $e->getMessage();
}

$destinationId = 0;
$stmt2 = $conn->prepare('SELECT source_external_subscriber_id, source_customer_cost FROM cdr WHERE destination_account_id = :destinationId GROUP BY source_external_subscriber_id');
$stmt2->execute(array('destinationId' => $destinationId));

foreach ($stmt as $row) {
     $datos[] = $row2;
}

Now I was wondering the right way to store the data so it looks something like this:

array = [
    0 => array(
            "id" => source_external_subscriber_id1,
            "total" => SUM(source_customer_cost)
         ),
    1 => array(
            "id" => source_external_subscriber_id2,
            "total" => SUM(source_customer_cost) 
         )...
];

Thank you all for the help, I hope you have a great day!

How to&Answers:

So if i understand you correctly, you’re searching for something like this:

SELECT source_external_subscriber_id id, (SELECT SUM(source_customer_cost)) total FROM cdr GROUP BY source_external_subscriber_id;

Answer:

So the answer to this one was as tricky as simple: the array returned by the query had duplicated rows, maybe I got wrong the for-each statement since I recently started using them. Anyways, here are both the query and my storage solution:

$destinationId = 0;
$stmt2 = $conn->prepare('SELECT source_external_subscriber_id, SUM(source_customer_cost) FROM cdr WHERE destination_account_id = :destinationId GROUP BY source_external_subscriber_id');
$stmt2->execute(array('destinationId' => $destinationId));

foreach ($stmt2 as $row2) {
    $data[] = $row2;
}

for ($i=0; $i < sizeof($data); $i++) { 
    $sanitizedData[$i] = array(
        0 => $data[$i][0],
        1 => $data[$i][1]
    );
}