This question already has answers here:
Subquery returning more than 1 row
(3 answers)
Closed 1 year ago.
I want to run a foreach loop from database, but I dont know how to start. I have an array which I have generated from a while loop:
/* mysql query for geting leave_type ID */
$leaveType = mysql_query("
SELECT `leave`.leave_type_id_leave_type,
`leave`.staff_leave_application_staff_id_staff,
`leave`.date,
`leave`.date_updated,
`leave`.active
FROM `leave`
WHERE `leave`.staff_leave_application_staff_id_staff = $iid
GROUP BY `leave`.leave_type_id_leave_type
");
/* Now put all leave Type ID in an array */
echo "<table>";
$types = array();
while($leaveFW = mysql_fetch_array( $leaveType )){
$types[] = $leaveFW['leave_type_id_leave_type'];
}
print_r($types);
Now I want to run a foreach loop which will query below code for each ID in array. :
$leaveQ = mysql_query("SELECT Count(*) as total, monthname(date) as
month FROM `leave`
WHERE `leave`.staff_leave_application_staff_id_staff = $iid
and `leave`.leave_type_id_leave_type = $type");
I want to show $leaveQ['month'] and $leaveQ['total'] in foreach loop.
May be my foreach like this, but how to get $type['month'] and $type['total'] :
foreach ($types as $type)
{
$leaveQ = mysql_query("SELECT Count(*) as total, monthname(date) as month
FROM `leave` WHERE `leave`.staff_leave_application_staff_id_staff = $iid
and `leave`.leave_type_id_leave_type = $type");
}
May youwant something like this
foreach($types as $result)
{
$iid = $result['staff_leave_application_staff_id_staff'];
$type = $result['leave_type_id_leave_type'];
$leaveQ = mysql_query("SELECT Count(*) as total, monthname(date) as
month FROM `leave`
WHERE `leave`.staff_leave_application_staff_id_staff = $iid
and `leave`.leave_type_id_leave_type = '".$leaveFW['leave_type_id_leave_type']."'");
while($row = mysql_fetch_assoc($leaveQ))
{
echo $row['month']."<br>";
echo $row['total']."<br>";
}
}
Don't do this!
mysql_ functions are deprecated as of PHP 5.5!
doing this (get one query, then run another query for each rows in a foreach loop) is a bad approach, commonly seen in a lot of code flying around the 'net...
Also, I think you want to get the count for each month; in that case you have to use the GROUP BY clause for that
The proper way to do this is using JOIN operations, and instead of a query for each line, only one query to get all the data.
Blindly following that advice, not changing too much, just merging the two queries, your query should look like this:
SELECT Count(*) as total, monthname(date) as month, types.leave_type_id_leave_type
FROM `leave`
JOIN (SELECT DISTINCT `leave`.leave_type_id_leave_type
FROM `leave`
WHERE `leave`.staff_leave_application_staff_id_staff = $iid) as types
ON leave.leave_type_id_leave_type = types.leave_type_id_leave_type
WHERE `leave`.staff_leave_application_staff_id_staff = $iid
GROUP BY monthname(date), types.leave_type_id_leave_type
Differences to your approach:
the inner query is almost the same as your 1st query, but
instead of GROUP BY, I used the DISTINCT - in this case, it is the same, but I think this is easier to read - and that is an important aspect!
I only selected the relevant column for it (leave_type_id_leave_type)
I altered the outer query a bit more
the JOIN does what replaces the "foreach" approach
only those rows are "taken into count" (in this case, literally :) ), that are appropriate for the inner query
this will return the count for each month and each type.
To make this even better:
Use properly parametrized prepared statements: better performance, and getting used to it makes you avoid SQL injection in situations where that applies...
you can use PDO for that, it is not deprecated...
Looking at the resulting query, it is easy to see that this can be further simplified, and does not need the inner query, also getting rid of one filter on $iid
SELECT Count(*) as total, monthname(date) as month, leave_type_id_leave_type
FROM `leave`
WHERE `leave`.staff_leave_application_staff_id_staff = $iid
GROUP BY monthname(date), leave_type_id_leave_type
Differences now:
huge performance jump...
a lot less, and a lot readable code
EDIT
Here is the SQL fiddle to see how this works
foreach($types as $type){
$leaveQ = mysql_query("SELECT Count(*) as total, monthname(date) as
month FROM `leave`
WHERE `leave`.staff_leave_application_staff_id_staff = $iid
and `leave`.leave_type_id_leave_type = $type");
while($leave = mysql_fetch_assoc($leaveQ)){
var_dump($leave['total'] , $leave['month']);
}
}
If I understand correctly you want to loop thru the types found from your block of code and then issue more database queries and extract more data.
You can basically reuse your first block of code again, wrapped with a foreach loop:
foreach($types as $type){
$query = mysql_query("YOUR_SQL_USING_$TYPE");
while($row = mysql_fetch_array( $query )){
print_r($row);
// or print($row['COLUMN_NAME']);...
}
}
Related
here's the code and i want to echo only 1 city from mysql database!
<?php
include('db.php');
$queryss = mysqli_query($conn, 'SELECT * FROM areas');
while ($rowx = mysqli_fetch_array($queryss)) {
echo "{pro:'$rowx[1]',city:'$rowx[2]', dist:'$rowx[3]', town:'$rowx[4]', area:'$rowx[5]',subarea:'$rowx[6]',ucname:'$rowx[7]'},";
}
?>
and i'm, getting this input here! 3 time karachi in my html, but i want only 1 of this city. SELECT DISTINCT is working in mysql but how can i use it in PHP?
Your query should be
SELECT * FROM areas GROUP BY id
I have tested it.
Use
SELECT DISTINCT column_name1,column_name2 FRAM areas
in your SQL where column_nameN stands for the columns you need for your output.
OR use something like this (untested):
$results = [];
while ($rowx = mysqli_fetch_array($queryss)) {
$results[] = $rowx;
}
$results= array_unique($results);
foreach($results as $rowx) {
echo "{pro:'$rowx[1]',city:'$rowx[2]', dist:'$rowx[3]', town:'$rowx[4]', area:'$rowx[5]',subarea:'$rowx[6]',ucname:'$rowx[7]'},";
}
First Solution
You can insert distinct keyword into your SQL to accomplish what you need, like so
SELECT DISTINCT your_column_name FROM table_name
Second Soltion
You can execute your SQL statement and then use array_unique, to be like so
$selectStatement = mysqli_query($con, 'SELECT * FROM areas');
$selectedArrayValues = mysqli_fetch_array($selectStatement);
$selectedUniqueArrayValues = array_unique(selectedArrayValues);
// Then return that array to your HTML code
I recommend the first solution because it's more optimized
I have a MySQL, PHP code as follows.
$sql = "SELECT * FROM shipschedule WHERE ship_date BETWEEN '2016-08-01' AND '2016-8-31'";
$result = $mysqli->query($sql);
$e = array();
while($r = $result->fetch_array()) {
$rows = array();
$rows['title'] = $r['title'];
$rows['start'] = $r['ship_date'];
array_push($e, $rows);
}
echo json_encode($e);
The above php code echos
[{"title":"111","start":"2016-08-10"},
{"title":"111","start":"2016-08-10"},
{"title":"111","start":"2016-08-10"},
{"title":"222","start":"2016-08-17"},
{"title":"222","start":"2016-08-17"},
{"title":"222","start":"2016-08-16"}]
My question is how I can echo the above as follow instead. Please see that duplicate start dates will be removed by title.
[{"title":"111","start":"2016-08-10"},
{"title":"222","start":"2016-08-17"},
{"title":"222","start":"2016-08-16"}]
title 111 has the same 3 start dates, and I need to display it like
{"title":"111","start":"2016-08-10"},
title 222 has the same 2 start dates, and I need to display it like
{"title":"222","start":"2016-08-17"},
{"title":"222","start":"2016-08-16"}]
You could prevent receiving duplicates, and reduce requesting unnecessary data by adjusting your query.
SELECT DISTINCT title, start FROM ...
It would be much easier (and probably faster too) to just get the right (unique) data from MySQL. This can be achieved with the distinct modifier:
SELECT DISTINCT title, start
FROM shipschedule
WHERE ship_date BETWEEN '2016-08-01' AND '2016-8-31'
This is 4 queries put into one. This is really old code and once I can make this work we can update it later to PDO for security. What I am trying to do is count rows from
select count(*) from dialogue_employees d_e,
dialogue_leaders d_l where
d_l.leader_group_id = d_e.leader_group_id
and use it in a formula where I also count how many rows from dialogue.status = 1.
The formula is on the bottom to create a percentage total from the results. This is PHP and MySQL and I wasn't sure the best way to count the rows and put them as a variable in php to be used in the formula on the bottom?
function calculate_site_score($start_date, $end_date, $status){
while($rows=mysql_fetch_array($sqls)){
$query = "
SELECT
dialogue.cycle_id,
$completecount = sum(dialogue.status) AS calculation,
$total_employees = count(dialogue_employees AND dialogue_leaders), dialogue_list.*,
FROM dialogue,
(SELECT * FROM dialogue_list WHERE status =1) AS status,
dialogue_employees d_e,
u.fname, u.lname, d_e.*
user u,
dialogue_list,
dialogue_leaders d_l
LEFT JOIN dialogue_list d_list
ON d_e.employee_id = d_list.employee_id,
WHERE
d_l.leader_group_id = d_e.leader_group_id
AND d_l.cycle_id = dialogue.cycle_id
AND u.userID = d_e.employee_id
AND dialogue_list.employee_id
AND site_id='$_SESSION[siteID]'
AND start_date >= '$start_date'
AND start_date <= '$end_date'";
$sqls=mysql_query($query) or die(mysql_error());
}
$sitescore=($completecount/$total_employees)*100;
return round($sitescore,2);
}
If you separate out your queries you will gain more control over your data. You have to be careful what your counting. It's pretty crowded in there.
If you just wanted to clean up your function you can stack your queries like this so they make more sense, that function is very crowded.
function calculate_site_score($start_date, $end_date, $status){
$query="select * from dialogue;";
if ($result = $mysqli->query($query))) {
//iterate your result
$neededElem = $result['elem'];
$query="select * from dialogue_list where status =1 and otherElem = " . $neededElem . ";";
//give it a name other than $sqls, something that makes sense.
$list = $mysqli->query($query);
//iterate list, and parse results for what you need
foreach($list as $k => $v){
//go a level deeper, or calculate, rinse and repeat
}
}
Then do your counts separately.
So it would help if you separate queries each on their own.
Here is a count example How do I count columns of a table
I'm try to display two data of one query using codeigniter.
$query = "SELECT count(distinct p.id_paciente), count(c.pacientes_id_paciente) FROM paciente p, cita c WHERE p.id_paciente=c.pacientes_id_paciente AND p.usuarios_id_usuario=43 AND p.aseguradoras_id_aseguradora=8 AND c.dia_cita>='2015-04-16' AND c.dia_cita<='2015-04-16'";
$sql = $this->db->query($query);
How can I to show the two results of count(distinct p.id_paciente) and the count(c.pacientes_id_paciente)
I try using
foreach ($sql->result_array() as $row)
{
echo $row['id_paciente'];
echo $row['pacientes_id_paciente'];
}
But only display the content of the array...
Thanks
There are several issues with your code:
Use aliases to name columns in the resultset to be able to address them later by name
SELECT COUNT(distinct p.id_paciente) AS count1, ...
^^^^^^
Don't interpolate query strings yourself. Use Codeigniter's query bindings
This may not be relevant to you but if dia_cita has time component to it (i.e. is of type datetime) you may want to change your WHERE condition to
c.dia_cita >= ? AND c.dia_cita < ? + INTERVAL 1 DAY
There is no need for foreach loop. You always get only one row with this query. Therefore use Codeigniter's row() or row_array().
That being said your code may look like
$sql = "
SELECT COUNT(DISTINCT p.id_paciente) AS count1,
COUNT(c.pacientes_id_paciente) AS count2
FROM paciente p JOIN cita c
ON p.id_paciente = c.pacientes_id_paciente
WHERE p.usuarios_id_usuario = ?
AND p.aseguradoras_id_aseguradora = ?
AND c.dia_cita >= ?
AND c.dia_cita < ? + INTERVAL 1 DAY
";
$bindings = array(43, 8, '2015-04-16', '2015-04-16')
$row = $this->db
->query($sql, $bindings)
->row_array();
echo $row['count1'], $row['count2'];
How can I make the following queries done in one single query and get the result just the way it is in below?
// Begining of January
$ob = mysql_query(" SELECT SUM(salary_amount) AS total FROM teacherexpense WHERE month(disburse_date)='01' AND year(disburse_date)='$year' ");
$nt = mysql_fetch_assoc($ob);
$salaryamount= $nt['total'];
$ob = mysql_query(" SELECT SUM(other_expense_amount) AS expenseamount FROM otherexpense WHERE month(other_expense_date)='01' AND year(other_expense_date)='$year' ");
$nt = mysql_fetch_assoc($ob);
$expenseamount= $nt['expenseamount'];
$jk = mysql_query(" SELECT SUM(amountpaid) AS revenue FROM studentpayment1 WHERE month(received_date)='01' AND year(received_date)='$year' ");
$t = mysql_fetch_assoc($jk);
$revenue= $t['revenue'];
$ob = mysql_query(" SELECT SUM(other_earning_amount) AS otherearningamount FROM otherearning WHERE month(other_earning_date)='01' AND year(other_earning_date)='$year' ");
$nt = mysql_fetch_assoc($ob);
$otherearningamount= $nt['otherearningamount'];
$January= ($revenue+$otherearningamount)-($salaryamount+$expenseamount);
// End of January
Stuff it in a Stored Procedure?
The database drivers for PHP won't let you run several queries separated with ; for security reasons.
Have you tried mysqli drivers instead of mysql?
Take a look at: mysqli_multi_query
Executes one or multiple queries which are concatenated by a semicolon.
SELECT 'withdrawals' t, SUM( amount ) sum
FROM withdrawals
UNION
SELECT 'statement' t, SUM( amount ) sum
FROM statement
while($row = mysql_fetch_assoc($result))
{
$total[$row['t']] = $row['sum'];
}
echo $total['withdrawals']; # 100
echo $total['statement']; # 624.x
You could use MySQL UNION - but you'll have to iterate over the resultset, because in that case you will get 4 records instead of one/statement group