php for each loop conditional total - php

I have a foreach loop, I am trying to get total count value which works fine. But the problem is that, most of the hard_disk3 column rows in database contains value "None", I want php to not count where row value is "None".
Here is the php code, what can I do to achieve this?
<?php
$type="systype, hard_disk3";
$typeQuery = $basequery." GROUP BY ".$type;
// Perform the Query
$objDbResultByType = $objDatabase->Query($typeQuery);
$imran9 = array();
foreach ($objDbResultByType as $row) {
$result = "{ label: \"".$row['systype']." ".$row['hard_disk3']."\", y: " .$row['total']." },";
array_push($imran9,$result);
}
$lastIndex = count($imran9)-1;
$lastValue = $imran9[$lastIndex];
$imran9[$lastIndex] = rtrim($lastValue, ',');
?>

You can achieve this in two ways, first one is already mentioned by Sherif (which is the better way to do that), second one in PHP is really easy. Try this:
<?php
$type="systype, hard_disk3";
$typeQuery = $basequery." GROUP BY ".$type;
// Perform the Query
$objDbResultByType = $objDatabase->Query($typeQuery);
$imran9 = array();
foreach ($objDbResultByType as $row) {
if ($row['hard_disk3'] == "None")
{
continue;
}
$result = "{ label: \"".$row['systype']." ".$row['hard_disk3']."\", y: " .$row['total']." },";
array_push($imran9,$result);
}
$lastIndex = count($imran9)-1;
$lastValue = $imran9[$lastIndex];
$imran9[$lastIndex] = rtrim($lastValue, ',');
?>
Or you could try:
if ($row['hard_disk3'] != "None") {
$result = "{ label: \"".$row['systype']." ".$row['hard_disk3']."\", y: " .$row['total']." },";
array_push($imran9,$result);
}

You should instead just specify that in your SQL query. SELECT COUNT(hard_disk3) FROM table WHERE hard_disk3 != "None" that way your dbms just returns the total row count and you neither need a foreach loop nor do you need PHP to do any real work to get to your result.

Related

Why do I have all of my results twice from my prepared statement?

I'm using sqlsrv_prepare()/sqlsrv_execute() for the first time. Until now, I've been using sqlsrv_query(). So far, I'm able to get the data that I need and I'm able to use the data effectively. The problem is that I have each value in my results array twice.
Clearly, I'm doing something to make this happen. Maybe I'm overlooking something obvious, or maybe I don't quite understand how sqlsrv_prepare()/sqlsrv_execute() work yet.
Here is an example of my PHP:
<?php
header("Content-type: text/javascript");
include($_SERVER['DOCUMENT_ROOT'] . "inc/dbconn.php");
include($_SERVER['DOCUMENT_ROOT'] . "inc/formaterrors.php");
// array populated from checkbox values
$items = (isset($_GET['checked'])) ? $_GET['checked'] : array();
// holds value of $i in foreach below - $i can't be used in sqlsrv_prepare() since it doesn't exist in this scope
$placeholder = '';
// variable from included dbconn.php file
$connectionOptions['Database'] = 'example_db';
$conn = sqlsrv_connect($serverName, $connectionOptions)
or die("Couldn't establish a database connection<br/>" . FormatErrors(sqlsrv_errors()));
$query = "
SELECT
detail.BILLNO,
detail.BILLTYPE,
detail.COMPONENTITEMCODE,
detail.QUANTITYPERBILL,
detail.REVISION,
header.BILLDESC1
FROM (BM_BILLDETAIL detail
JOIN BM_BILLHEADER header
ON (detail.BILLNO = header.BILLNO)
AND (detail.BILLNO = ?)
AND (header.REVISION = header.CURRENTBILLREVISION)
AND (detail.REVISION = header.CURRENTBILLREVISION)
and (detail.ENGINEERINGCHANGEDELNO = ''))
";
$results = array();
$stmt = sqlsrv_prepare($conn, $query, array(&$placeholder));
if(!$stmt)
{
die(print_r(sqlsrv_errors(), true));
}
foreach($items as $i)
{
$placeholder = $i;
if(sqlsrv_execute($stmt))
{
while($row = sqlsrv_fetch_array($stmt))
{
$results[] = $row;
}
} else
{
die(print_r(sqlsrv_errors(), true));
}
}
// diplay results as JSON
echo(var_dump(json_encode($results, JSON_PRETTY_PRINT)));
?>
And here is an example of my results in JSON:
{
"0": "TRC4009-C005",
"BILLNO": "TRC4009-C005",
"1": "",
"BILLTYPE": "",
"2": "110500001153-00",
"COMPONENTITEMCODE": "110500001153-00",
"3": "1.000000",
"QUANTITYPERBILL": "1.000000",
"4": "001",
"REVISION": "001",
"5": "TRC4009, 8155, Red 800W",
"BILLDESC1": "TRC4009, 8155, Red 800W"
}
So I've got key => value pairs, which is what I want. I don't want the "numbered" keys though. Only the field name keys, i.e., "BILLNO", "REVISION", etc.
Ultimately, my tool still works like this; however, I don't want to double the number of results that I'm sending/receiving/processing each time. In most cases, this will be executed hundreds or thousands of times and the number of results can vary greatly.
Any help/insight is appreciated.
You have to specify a fetch type for sqlsrv_fetch_array if you only want to get the text keys. The default fetch type is SQLSRV_FETCH_BOTH, which is why you're getting both text and numeric keys.
You want to use sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) instead.

For each / query doesn't give the right value

I have a table in my database. I want to get ltotal value from leave table, and then count all of ltotal. Here are my query and code I use:
$annual_query = pg_query("select ltotal from leave where lapplicant='adam' and ltype=2");
$annual_result = pg_fetch_array($annual_query);
if (pg_num_rows($annual_query) > 0) {
foreach ($annual_result as $data) {
$total_annual = $total_annual + $data;
}
print($total_annual);
}
There are 3 records in the table leave where lapplicant='adam' and ltype=2.
Each ltotal is 1.
When I tried to runprint($total_annual) the result is 2 (it must be 3).
Then I tried to print_r($annual_result['ltotal']), the results is just 1 (it must be 1,1,1).
Can anyone help me? Thank you.
pg_fetch_array() returns just one row with numeric and associative keys (same value twice when traversed). You should use pg_fetch_all() and traverse or use while loop on consecutive rows.
$total_annual = 0;
$annual_query = pg_query("select ltotal from leave where lapplicant='adam' and ltype=2");
while ($row = pg_fetch_array($annual_query)) {
$total_annual = $total_annual + $row['ltotal'];
}
print($total_annual);
or
$total_annual = 0;
$annual_query = pg_query("select ltotal from leave where lapplicant='adam' and ltype=2");
$annual_result = pg_fetch_all($annual_query);
foreach ($annual_result as $row) {
$total_annual = $total_annual + $row['ltotal'];
}
print($total_annual);
Tamil pointed out the immediate problem. However - why don't you just do this in SQL?
select sum(ltotal)
from leave
where lapplicant='adam' and ltype=2

Loop through an array to create an SQL Query

I have an array like the following:
tod_house
tod_bung
tod_flat
tod_barnc
tod_farm
tod_small
tod_build
tod_devland
tod_farmland
If any of these have a value, I want to add it to an SQL query, if it doesnt, I ignore it.
Further, if one has a value it needs to be added as an AND and any subsequent ones need to be an OR (but there is no way of telling which is going to be the first to have a value!)
Ive used the following snippet to check on the first value and append the query as needed, but I dont want to copy-and-paste this 9 times; one for each of the items in the array.
$i = 0;
if (isset($_GET['tod_house'])){
if ($i == 0){
$i=1;
$query .= " AND ";
} else {
$query .= " OR ";
}
$query .= "tod_house = 1";
}
Is there a way to loop through the array changing the names so I only have to use this code once (please note that $_GET['tod_house'] on the first line and tod_house on the last line are not the same thing! - the first is the name of the checkbox that passes the value, and the second one is just a string to add to the query)
Solution
The answer is based heavily upon the accepted answer, but I will show exactly what worked in case anyone else stumbles across this question....
I didnt want the answer to be as suggested:
tod_bung = 1 AND (tod_barnc = 1 OR tod_small = 1)
rather I wanted it like:
AND (tod_bung = 1 OR tod_barnc = 1 OR tod_small = 1)
so it could be appended to an existing query. Therefore his answer has been altered to the following:
$qOR = array();
foreach ($list as $var) {
if (isset($_GET[$var])) {
$qOR[] = "$var = 1";
}
}
$qOR = implode(' OR ', $qOR);
$query .= " AND (" .$qOR . ")";
IE there is no need for two different arrays - just loop through as he suggests, if the value is set add it to the new qOR array, then implode with OR statements, surround with parenthesis, and append to the original query.
The only slight issue with this is that if only one item is set, the query looks like:
AND (tod_bung = 1)
There are parenthesis but no OR statements inside. Strictly speaking they arent needed, but im sure it wont alter the workings of it so no worries!!
$list = array('tod_house', 'tod_bung', 'tod_flat', 'tod_barnc', 'tod_farm', 'tod_small', 'tod_build', 'tod_devland', 'tod_farmland');
$qOR = array();
$qAND = array();
foreach ($list as $var) {
if (isset($_GET[$var])) {
if (!empty($qAND)) {
$qOR[] = "$var = 1";
} else {
$qAND[] = "$var = 1";
}
$values[] = $_GET[$var];
}
}
$qOR = implode(' OR ', $qOR);
if ($qOR != '') {
$qOR = '(' . $qOR . ')';
}
$qAND[] = $qOR;
$qAND = implode(' AND ', $qAND);
echo $qAND;
This will output something like tod_bung = 1 AND (tod_barnc = 1 OR tod_small = 1)
As the parameter passed to $_GET is a string, you should build an array of strings containing all the keys above, iterating it and passing the values like if (isset($_GET[$key])) { ...
You could then even take the key for appending to the SQL string.
Their are a lot of ways out their
$list = array('tod_house', 'tod_bung', 'tod_flat', 'tod_barnc', 'tod_farm', 'tod_small', 'tod_build', 'tod_devland', 'tod_farmland');
if($_GET){
$query = "";
foreach ($_GET as $key=>$value){
$query .= (! $query) ? " AND ":" OR ";
if(in_array($key,$list) && $value){
$query .= $key." = '".$value."'";
}
}
}
Sure you have to take care about XSS and SQL injection
If the array elements are tested on the same column you should use IN (...) rather than :
AND ( ... OR ... OR ... )
If the values are 1 or 0 this should do it :
// If you need to get the values.
$values = $_GET;
$tod = array();
foreach($values as $key => $value) {
// if you only want the ones with a key like 'tod_'
// otherwise remove if statement
if(strpos($key, 'tod_') !== FALSE) {
$tod[$key] = $value;
}
}
// If you already have the values.
$tod = array(
'tod_house' => 1,
'tod_bung' => 0,
'tod_flat' => 1,
'tod_barnc' => 0
);
// remove all array elements with a value of 0.
if(($key = array_search(0, $tod)) !== FALSE) {
unset($tod[$key]);
}
// discard values (only keep keys).
$tod = array_keys($tod);
// build query which returns : AND column IN ('tod_house','tod_flat')
$query = "AND column IN ('" . implode("','", $tod) . "')";

Break a special character in MySQL

I have a requirement where I need to check a pipe | in the database. If found I need to play around differently.
Here how my db table looks like //Please check the | character in row 11
And if I run a group by sql command myresult will be
Which is correct.
But my requirement is to break the | in any cell and give the count accordingly. The expected result as
Can this be done using MySQL commands alone or do I need to use some php script as well?
Any snippet will be helpful.
Hope this script might help u
$frt =array();
$stmt = $mysqli->prepare("select `fruits` from `meva`") or $mysqli->error ;
$stmt->execute();
$stmt->bind_result($fruits);
while ($stmt->fetch()) {
$frt[]=$fruits;
}
// var_dump($frt); //check all the fruits is in array
$res = array();
$tot = count($frt);
for($i=0;$i<=$tot;$i++)
{
if(preg_match("/\|/", $frt[$i]))
{
$res[] =explode( '|', $frt[$i]);
}else
{
$res[] = $frt[$i];
}
}
// var_dump($res);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($res));
foreach($it as $v) {
$ary[]=$v;
}
$all_fruits = array();
$tot_ary = count($ary);
for($io=0;$io<=$tot_ary;$io++)
{
if(isset($ary[$io])!='')
{
$all_fruits[] = trim($ary[$io]);
}else
{
continue;
}
}
// var_dump($all_fruits);
$newArray = array_count_values($all_fruits);
foreach ($newArray as $key => $value) {
echo "$key - <strong>$value</strong> <br />";
}
I think you should fix your data. You can run these two statements in a row until all the data is fixed:
INSERT INTO meva (fruits)
SELECT SUBSTR(fruits, LOCATE('|', fruits) - 1) FROM meva
WHERE LOCATE('|', fruits) > 0;
UPDATE meva
SET fruits = SUBSTR(fruits, LOCATE('|', fruits) + 1)
WHERE LOCATE('|', fruits) > 0;
This will fix the table.
However, if it is your interview question (or a school assignment) just to count from the table as it is, then you can only do it if you know the maximum number of pipes in a given row.
So, if the maximum number of pipes in a row is 1, then your select statement would be:
SELECT count(*),
CASE WHEN LOCATE('|', fruits) > 0 THEN SUBSTR(fruits, LOCATE('|', fruits) - 1) ELSE fruits END
FROM meva
GROUP BY CASE WHEN LOCATE('|', fruits) > 0 THEN SUBSTR(fruits, LOCATE('|', fruits) - 1) ELSE fruits END
If you can have more than one pipe in a row, then your CASE statement will be more complex
Actually the best solution is to change your data structure. This current structure is not recommended. each 'cell' has to contain only one value. If you need to store several fuirts for a specific ID, use
id fruit
11 Apple
11 Mango
this might require some adjustments to your code / tables, but it will prevent the need for more future hacks.
You can use php and do it like below
$query = mysql_query("SELECT fruit FROM meva");
$cnt_array = array();
while($row = mysql_fetch_assoc($query)){
$fruits = $row["fruit"];
$fruit = explode("|", $fruits);
foreach($fruit as $fru){
if(array_key_exists($fru,$cnt_array)){
$cnt_array[$fru] = $cnt_array[$fru]+1;
}
else{
$cnt_array[$fru] = 1;
}
}
}
print_r($cnt_array);
NOTE : This code is not tested,please try it and edit accordingly

PHP SQL where statement with loop variable

I am having problems with the retrieval of data from my database using a where clause with a for loop variable. this codes currently can retrieve the data from the database but however the values retrieved from the database stockpiles. at the number 1 in the for loop its still fine. but when it goes to the next one. the data gathered is the combination of 1 and 2. when it finally hit the end of the loop all of the data is displayed.
Which part of the codes must be edited to change the display of data to non-cumulative
<?php
$sectorcount = $row_SectorCount['COUNT(*)'];
//number of rows in database
$spendingname= array();
$spendingpercent= array();
$spendingid= array();
?>
// Add some data to the details pie chart
options_detail_1.series.push({ name: 'Tax Spending Detail', data: [] });
$(document).ready(function() {
chart_main = new Highcharts.Chart(options_main);
chart_detail_1 = new Highcharts.Chart(options_detail_1);
})
function push_pie_detail(sectorid) {
switch(sectorid)
{
<?php
for ($i=1; $i<=$sectorcount; $i++)
{
echo "case 'sector".$i."':" ,
"setTimeout", "(" , '"chart_detail_1.series[0].remove(false)", 1000);' ,
"chart_detail_1.addSeries(options_detail_1, false);" ,
"chart_detail_1.series[1].setData( [";
mysql_select_db($database_conn2, $conn2);
$query_Spending = "SELECT CONCAT(spending.SectorID, spending.ExpenditureID) AS 'SpendingID',
expenditure.ExpenditureName, spending.SpendingPercent, spending.SectorID
FROM spending
INNER JOIN expenditure ON spending.ExpenditureID = expenditure.ExpenditureID
WHERE spending.SectorID = '.$i.'";
$Spending = mysql_query($query_Spending, $conn2) or die(mysql_error());
$totalRows_Spending = mysql_num_rows($Spending);
while($row_Spending = mysql_fetch_assoc($Spending))
{
$spendingname[] = $row_Spending['ExpenditureName'];
$spendingpercent[] = $row_Spending['SpendingPercent'];
$spendingid[]= $row_Spending['SpendingID'];
}
mysql_free_result($Spending);
$a = 0;
foreach ( $spendingid as $sgi => $sgid)
{
if ($a > 0) echo ', '; // add the comma
echo "{
name: '$spendingname[$sgi]',
y: ". $spendingpercent[$sgi] * $tax .",
id: ' $sgid',
}";
$a++;
}
echo "], false);" ,
"chart_detail_1.redraw();",
"break;";
}
?>
default:
break;
}
}
You need to wrap your variable in 'x' single quotes in your where clause, otherwise it will think you mean id = true, which is true for all of them =) I had the same problem recently
EDIT: So instead of saying where spending.SectorID = $i, you should have 'somevalue', just make a new variable $example = "'" . $i . "'", and use that variable in the where clause
I wrote a function that takes text and wraps it in single quotes just for this situation
Move your $spendingname = array(); and other array definitions inside the loop.

Categories