-1

I am doing a project with PHP and MySQL. I have this problem.

This is my code

<?php 

$proyecto = $_POST['id'];

$servername = "localhost";
$username = "dbuser";
$password = "dbpass";
$dbname = "proyectos";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
  die("Connection failed: " . $conn->connect_error);
}

$sql = "SELECT `horas`, `trabajador` FROM `horas` WHERE `proyecto` LIKE '$proyecto' ";
$result = $conn->query($sql);
$conn->close();

?>

It takes a parameter from a post request and do a search in the database database looks like this:
database looks like this

So I want to get as result the sum of all the hours (horas column) that are made by the same worker (trabajador column). Example of result:

Prueba1: 8 hours in total, Prueba2: 9 hours in total

I am stuck trying to dinf they way to sum when 1 or more fields must be the same, I hope someone can help me with this. Thanks!

  • 2
    Start by explain where you're stuck. You're making a query to the database, then what happens? You're also _wide open_ for [SQL injection](https://owasp.org/www-community/attacks/SQL_Injection) attacks! You should use parameterized [prepared statements](https://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php) instead of using completely unescaped user data directly in your queries like that. _Never ever ever never_ trust user input. – M. Eriksson Aug 08 '20 at 10:55
  • **Warning:** You are wide open to [SQL Injections](https://stackoverflow.com/a/60496/1839439) and should use parameterized **prepared statements** instead of manually building your queries. They are provided by [PDO](https://php.net/manual/pdo.prepared-statements.php) or by [MySQLi](https://php.net/manual/mysqli.quickstart.prepared-statements.php). Never trust any kind of input! Even when your queries are executed only by trusted users, [you are still in risk of corrupting your data](http://bobby-tables.com/). [Escaping is not enough!](https://stackoverflow.com/q/5741187) – Dharman Aug 08 '20 at 10:56
  • 1
    You should also use `=` instead of `LIKE` when matching an exact string in MySQL. – M. Eriksson Aug 08 '20 at 10:56
  • Yes, I know the sql injection part but I am only going to use it (localhost) so it isn't so important. I am stuck in this part: "So I want to get as result the sum of all the hours (horas column) that are made by the same worker (trabajador column)." – Alvaro Artano Aug 08 '20 at 10:57
  • 1
    Because your question is missing an actual explanation of your issue. You've just posted some code and a requirements spec. without even commenting on it. Is it fetching the data from the database result? Is it the calculation? If yes, then what does any of those columns contain? Show us the database schema and some example data, expected result and what you're currently getting. – M. Eriksson Aug 08 '20 at 11:04
  • Adding data/code samples as image isn't a good solution. – biesior Aug 08 '20 at 11:12
  • That still doesn't change the fact that we programmers would prefer to see [SHOW CREATE TABLE](https://dev.mysql.com/doc/refman/8.0/en/show-create-table.html) instead of graphic arts. – biesior Aug 08 '20 at 11:19
  • lol it's not a big table so it's more visual to see it with an image I think. – Alvaro Artano Aug 08 '20 at 11:21
  • Not for me, like in Matrix movie, you can see a blondies and brunets here, I can see tables and columns :p. And more seriously. after this screenshot, we don't know i.e. what data types are specified for the columns (although it doesn't matter in this case of course). Therefore it's better to show create statement as text. Back to your problem. `sum()` function is probably thing you should check. Anyway as other commented you **MUST** use prepared statements for security reasons. – biesior Aug 08 '20 at 11:28
  • Ok. Thanks, It's my first time showing mysql problems in the platform so I don't know how to do it well. Thanks – Alvaro Artano Aug 08 '20 at 11:30
  • Votes are how we rate content. This question doesn't add anything new to our collection of questions so it will not be rated high. Don't take downvotes personally, we simply rate the content to have a proper collection of questions & answers. – Dharman Aug 08 '20 at 16:41
  • Does this answer your question? [Get sum of MySQL column in PHP](https://stackoverflow.com/questions/5808522/get-sum-of-mysql-column-in-php) – Dharman Aug 08 '20 at 16:42

2 Answers2

2

You must use sum function to add the number of hours for each worker along with GROUP BY clause to group workers.Formatted Query is like:

SELECT SUM(horas) AS Hours,`trabajador` 
FROM `horas` 
WHERE `proyecto` 
LIKE '%".$proyecto."%' 
GROUP BY `trabajador`

In your code,

$select = "
    SELECT SUM(horas) AS Hours, `trabajador` 
    FROM `horas` 
    WHERE `proyecto` LIKE ? 
    GROUP BY `trabajador`
";

$sth = $conn->prepare($select);
$sth->execute(['%'.$proyecto.'%']);

/* Fetch all of the remaining rows in the result set */
print("Fetch all rows in the result set:\n");
$result = $sth->fetchAll(\PDO::FETCH_ASSOC);
print_r($result);

Note: You better switch to MYSQL prepared statements to keep your data secure and for better database connectivity practices.

biesior
  • 55,576
  • 10
  • 125
  • 182
my_workbench
  • 300
  • 3
  • 8
1

Note answer by maniksidana explains how to use SUM() and GROUP BY and is in general valid. However, it mixes mysqli and PDO approches. Here you have sample how to use it with mysqli (as your question uses it) and why it's important to use prepared statements at all. Just add some dummy data to your table end execute it. Personally I'd suggest to go with PDO only instead, but it's matter of taste.

INSERT INTO `horas` (`fecha`, `horas`, `proyecto`, `trabajador`) VALUES
 ('2020-08-08', 3, 'foo bar baz', 'Joker1'),
 ('2020-08-09', 4, 'ello pomello', 'Joker2');
<?php 

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}


$proyecto = "ProyectpDePrueba'; DELETE FROM horas WHERE 1; -- bye bye data";
$proyecto = "ProyectpDePrueba";
$proyecto = "ProyectpDePrueba' OR 1=1 -- no more execution";


// Wrong
$sql = "
    SELECT SUM(horas) AS Hours, `trabajador` 
    FROM `horas` 
    WHERE `proyecto` LIKE '$proyecto'
    GROUP BY `trabajador`
";
$result = $conn->query($sql);
echo '<pre>Wrong' . PHP_EOL;
while ($row = mysqli_fetch_assoc($result)) {
    print_r($row);
}

// Correct
$sql = "
    SELECT SUM(horas) AS Hours, `trabajador` 
    FROM `horas` 
    WHERE `proyecto` LIKE ? 
    GROUP BY `trabajador`
";
$stmt = $conn->prepare($sql);
$stmt->bind_param('s', $proyecto);
$stmt->execute();
$result = $stmt->get_result();
echo PHP_EOL . 'Corrcet' . PHP_EOL;
while ($row = $result->fetch_assoc()) {
    print_r($row);
}


$conn->close();
biesior
  • 55,576
  • 10
  • 125
  • 182
  • Why do you show both the wrong an correct way? Would it not be simpler to just show the correct way? – Dharman Aug 08 '20 at 16:35
  • It's for demonstrating why it's important. I'm still surprised why people don't understand that. At least OP (or any) can copy this and see what's the differece. – biesior Aug 08 '20 at 16:47
  • Yeah, but I don't think this question adds anything new to the SO. I think I will vote to delete this in 2 days. – Dharman Aug 08 '20 at 16:49
  • Its quite possible, especially, that has lot of duplicates, just let's hope that at least OP will learn some **basics**. If it was experienced, contributor I would end with rude comment and downvote. – biesior Aug 08 '20 at 16:51
  • I don't think any contributor deserves a rude comment. Downvote based on the content is appropriate. – Dharman Aug 08 '20 at 16:55