Specifying conditions on database results to array - php

In my database I have a field called "modules" - info data looks like this: 1, 4, 1, 3
I want to list/output all data via PHP with the numbers 1 - all other numbers have to be ignored.
I want to check the output result via an array NOT via mySQL
Any suggestion how I can do that?
$list_modules = array();
$res_m = $db->Execute("SELECT modules FROM users u WHERE user_id = '".$user->id."'");
while ( $m = $res_m->GetNext() ) {
$list_modules = array($m['modules']);
}
print_r($list_modules); //Output below
Example (Output):
Array
(
[0] => 1, 4, 1, 3
)

You can do that in you MySQL with a WHERE clause. Depending on the column name in the database:
SELECT column_name FROM table WHERE column_name = 1;
Note: In your question it looks like you tried to list a range:
with the numbers 1 - all other numbers have to be ignored.
If you meant to put a range (e.g. 1 - 4) then your WHERE clause would be:
WHERE column_name BETWEEN 1 AND 4

You should test for that in your MySQL query:
SELECT * FROM `TABLE` WHERE `modules` = 1;
Or, alternatively, if that's not possible..
Loop with foreach and test for 1?
$array = array(1,4,1,3);
foreach ($array as $element) {
if ($element == 1) { echo 1; }
}

This should do it... there is really no other way seeing at the col is Varchar, you also need to eliminate strings like 15, 21, etc. so %1% will not work.
SELECT modules FROM users WHERE user_id = ".$user->id." AND modules LIKE % 1,%
Give it a shot and let me know if it works.

You stated in your comment that the modules field contains comma-separated values, is that right? I reckon that the modules field is VARCHAR, CHAR, or any other string. If so, you could use a query like:
SELECT * FROM `tableName` WHERE `modules` LIKE '%1,%';
There may be other solutions, probably more optimal, but this one should perform well, I think.

Meh found the solution I could use.
$list_modules = array();
$query = "SELECT modules FROM users WHERE user_id = ".$user->id."";
$res_m = $db->Execute($query);
while ( $m = $res_m->GetNext() ) {
$list_modules = array('id' => $m['modules']);
}
$modules = explode(",",$list_modules['id']);
foreach ($modules as $key => $value) {
if($value == 1){
// list data
}
}
}

Related

PHP: If MYSQL Result greater than 0, add to array?

I have a MYSQL table with a list of services that user's provide:
The Enum values in these columns can be 0 or 1.
0 represents a service not offered and 1 represents a service offered.
Cleaning Tour Guide Cooking Parties
0 1 0 1
I am then running the following query In MYSQL to fetch my rows in the table:
<?php $myBio = $conn->query("SELECT * FROM user_data, user_services WHERE user_data.user_id = user_services.user_id AND user_id = $p_id");
if ($myBio->num_rows > 0) {
$row = $myBio->fetch_assoc();?>
I want to generate a list of the services the user provides (where the service has a value greater than 0) - and separate the list with commas like so:
Tour Guide, Parties
I am trying to do this by using an array:
$os = array(if($row['cleaning'] > 0) { echo 'cleaning';}, if($row['tour'] >0) { echo 'Tour Guide'; });
I am trying to use PHP if statements to decipher if a service is 0 or 1 before adding it to my list.
I do not believe it is possible to combine php if statements within an array.
Please can someone show me how I can achieve my desired result? Thanks in advance
Use array_keys() with the optional search parameter:
$services = array_keys($row, 1);
Example:
$row = [
'Cleaning' => 0,
'Tour Guide' => 1,
'Cooking' => 0,
'Parties' => 1,
];
$services = array_keys($row, 1);
var_export($services);
Result:
array (
0 => 'Tour Guide',
1 => 'Parties',
)
Demo
If your database columns have a speaking name, you can do it like this:
<?php
$arrayServices = array();
$arrayAllServices = array('Cleaning','Tour Guide','Cooking','Parties');
foreach($arrayAllServices as $service) {
if($row[$service] > 0) {
$arrayServices[] = $service;
}
}
$sServices = join(', ', $arrayServices);
echo $sServices;
If the speaking names are different from the column names, you need a second array to look up translations.
Would something like this achieve what you want?
$results=array();
if ($row['cleaning']>0) $results[]='Cleaning';
if ($row['tour']>0) $results[]='Tour Guide';
// ...
Also, please heed #tadman's comment about prepared statements!
<?php
$myResults = array();
$myBio = $conn->query("SELECT * FROM user_data, user_services WHERE user_data.user_id = ? AND user_id = ?");
$stmt->bind_param("ss",$user_services.user_id,$p_id);
$stmt->execute();
$result = $stmt->get_result();
if($result->num_rows === 0) exit('No rows');
while($row = $result->fetch_assoc())
{
$tempArray = array();
$Cleaning = $row['Cleaning'];
$Tour_Guide = $row['TourGuide'];
$Cooking = $row['Cooking'];
$Parties = $row['Parties'];
if($Cleaning == 1)
array_push($tempArray,$Cleaning)
if($Cleaning == 1)
array_push($tempArray,$Cleaning)
if($Cooking == 1)
array_push($tempArray,$Cooking )
if($Parties == 1)
array_push($tempArray,$Parties )
array_push($myResults,$tempArray);
}
?>
You will then get the myResult array which will be an array of arrays, you can then loop over the sub arrays to check values and construct the strings you intend to make.

Iterating through PHP array with duplicate records and deleting one record where a value = 0

I have a MySQL query using Laravel that I convert to a PHP Array.
The rows have values similar to this:
name | override | percentage
Eclipse | 1 | 50%
Eclipse | 0 | 75%
MySQL query
select * from table
Both rows (it's many more than just 2 in reality) have the same name, but one has override set to 0 and one has it set to 1.
How can I get rid of all records in my query result (PHP array) that are duplicates (determined by the name) AND have override set to 0? I want only the records that have been overridden with a new record which I have done, but I need a way to remove the records with override = 0, given that the records are the same but have a different percentage value.
How can this be done?
Thanks.
Try following query,
SELECT * from testtable GROUP BY `name` HAVING count(`name`) = 1 OR `override` = 1;
check this sqlfiddle
If I understand your needs correctly, you need to filter out records that have duplicate name and override = 0.
If you sort your result set by name (SELECT * FROM TABLE ORDER BY name), you can use this function.
function removeDuplicatesFromArray($rows) {
$result = array();
$old_name = '';
foreach($rows as $row) {
if($row['name'] != $old_name) {
$result[] = $row;
$old_name = $row['name'];
}
elseif($row['override'] == 1) {
array_pop($result);
$result[] = $row;
}
}
return $result;
}
NOTE: Doing this in SQL will be WAYYYYYYYYY faster and use far less memory. I would only try this PHP approach if you cannot modify the SQL for some reason.
Maybe try out... hit the db twice, first time only get non-overrides, then get the overrides in second pass -- coerce your arrays to be indexed by name and array_merge them. (Uses a fair chunk of memory given the number of arrays and copies - but it's easy to understand and keeps it simple.
$initial = get_non_overridden();
$override = get_overridden();
$init_indexed = index_by_name($initial);
$over_indexed = index_by_name($override);
$desired_result = array_merge($init_indexed, $over_indexed);
Assuming your database gives you a standard rowset (array of rows, where each row is a hash of fields->values). We want something that looks like this instead:
[
'Eclipse' => [
'name' => 'Eclipse',
'override' => '0',
'percentage' => '75%'
],
'Something' => [
'name' => 'Something',
'override' => '0',
'percentage' => '20%'
],
]
So index_by_name would be:
function index_by_name($rowset) {
$result = array();
foreach ($rowset as $row) {
$result[ $row['name'] ] = $row;
}
return $result;
}
There are ways to tweak your efficiency either in memory or run time, but that's the gist of what I was thinking.
array_merge then overwrites the initial ones with the overridden ones.
NOTE: this all assumes that there is only one row where Eclipse override is 1. If you have twenty Eclipse|0 and one Eclipse|1, this will work, if you have two Eclipse|1 you'd only see one of them... and there's no way to say which one.

How can I loop through an array while averaging the values of one element and only keep the newly averaged field in PHP?

I have database that contains scores which are stored daily. I want to average each months scores for each user. So far I have this:
DB structure:
id | name | tscore | added
int| string | float(100 or less)| date(2014-01-01 16:34:22)
Code:
while($row = mysql_fetch_assoc($getChartData)){ // Data from MySQL
$added_date = explode(' ',$row['added']); // Date formate 2014-01-01 16:34:22
$chartData[] = array(
'id' => $row['name'],
'tscore' => $row['tscore'],
'added' => $added_date[0] // Here I take the month only
);
}
if($_POST['range'] == 'month'){
foreach($chartData as $key => $value){
$added = explode('-',$chartData[$key]['added']);
$count = 1;
foreach($chartData as $key2 => $value2){
$added2 = explode('-',$chartData[$key2]['added']);
if($chartData[$key]['id'] === $chartData[$key2]['id'] && $added[1] === $added2[1]){ // if user is the same and the month is the same, add the scores together, increment counter, and unset 2nd instance
$chartData[$key]['tscore'] = ((float)$chartData[$key]['tscore'] + (float)$chartData[$key2]['tscore']);
$count++;
unset($chartData[$key2]);
}
}
$chartData[$key]['tscore'] = ($chartData[$key]['tscore']/$count); // Average all the scores for the month.
}
}
The problem is this method is deleting all the elements of the $chartData array. What can I try to resolve this?
You should try to solve it with MySQL. Try something like this (replace 'your_scores_table' with your table name):
SELECT
Score.name,
AVG(Score.tscore) AS `avg`,
CONCAT(YEAR(Score.added), '-', MONTH(Score.added)) AS `year_month`
FROM
your_scores_table AS Score
GROUP BY
Score.name ASC,
YEAR(Score.added) DESC,
MONTH(Score.added) DESC
;
Your logic is wrong. You are looping through the same array twice. Which means that the following if will always evaluate to true which means that array item will always get unset
//This will always be true
if($chartData[$key]['id'] === $chartData[$key2]['id'] && $added[1] === $added2[1]){
It may be simpler for you to create another array where you keep your scores. Something like
$aScores = array();
$count = 1;
foreach($chartData as $key => $value){
//Add score to a different array
$aScores[$value['name']]['tscore'] = (($aScores[$value['name']]['tscore'] + $value['tscore']) / $count);
$count++;
}
Also I would look into the MySQL AVG function. You could use that to save you having to do it in PHP

Count unique value from associative array

First, thanks for any help.
I've spent countless hours on here and other forums trying to find my exact solution but either 1) I'm not understanding the one's I've read or 2)I haven't found the right answer.
In PHP, I've run a somewhat complex query which returns a set of records similar to:
id | name | direction|
1 aaa east
2 bbb west
3 ccc east
I've created an associative array such as:
$query=("select * from foo");
$result=mysql_query($query);
$array=mysql_fetch_assoc($result);
Now, what I need to do seems simple but I'm not grasping the concept for some reason.
I need to loop through the entire $array and return a count of any value that I want to specify and store that count in a variable.
i.e. Show me how many times east shows up in the "direction" column and put that in a variable called $eastcount.
I've tried various combinations of using foreach loops with incremental counts and have tried using array_count_values but have not been able to put the pieces together :/
// build query
$query=("select * from foo");
// execute query
$result=mysql_query($query);
// declare vars
$east_count = 0;
// iterate through results
while ($data = mysql_fetch_array($result)) {
// grab DIRECTION column value
$direction = $data['direction'];
// detect 'east'
if ($direction == 'east') {
// increment 'east' count
$east_count++;
}
}
// print # of times we had 'east'
echo("direction said 'east' $east_count times");
This should work (sorry for the lack of code block I'm on my iPhone).
http://www.php.net/manual/en/function.array-count-values.php
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
Array
(
[1] => 2
[hello] => 2
[world] => 1
)
How about this:
query=("select * from foo");
$result=mysql_query($query);
$directions = array();
while($direction = mysql_fetch_assoc($result) {
$directions[] = $direction['direction'];
}
$directionCounts = array_count_values($directions);
//now you can access your counts like this:
echo $directionCounts['east'];
First, of all you should be using mysqli instead. But, anyhow I hope this makes some sense.
if ($result) {
$count = 0;
while ( $row = mysql_fetch_assoc($result)) {
if ($row["route"] === "east") {
$count += 1;
}
}
return $count;
}

How to make a "distinct" detection on a foreach loop

At this time I have this very complex query that I loop through and I get something like this:
List of Challenges:
TEAM A
- Challenge 1
TEAM A
- Challenge 4
TEAM A
- Challege 6
And I want to change to something like:
TEAM A
- Challenge 1
- Challenge 4
- Challenge 6
My question is, since the query is a very complex one, maybe I could do this inside the loop but, if that's the case, how can we achieve something like that?
Can I ask an example case so that I can use, in order to solve this issue?
Thanks a lot,
MEM
UPDATE:
The query is something like this:
Translated:
public function listachallengesPendentes()
{
$select = $this->getAdapter()->select();
$select->from(array("e"=>"teams"),array('name'));
$select->join(array("de"=>"challengeperteam"),"e.cod_team = de.cod_teamFk",array());
$select->join(array("d"=>"challenges"),"d.cod_challenge = de.cod_challengeFk",array('title'));
$select->columns(array("e.cod_team"
,"name_team"=>"e.name"
,"d.cod_challenge"
,"name_challenge"=>"d.title"
,"d.details"
,"d.score"
,"category"=>"d.cod_categoryFk"
,"de.proof"
,"de.date_concluded"
,"de.cod_challenge_team"
));
$select->where("de.status = 0");
$select->order(array('e.cod_team DESC', 'de.cod_challenge_team DESC'));
return $this->getAdapter()->fetchAll($select);
}
So I need to add a distinct some part :s :D ?
The foreach actually is pretty basic:
foreach ($challenges as $d){
//display the name:
echo $d['name_team'];
...
}
UPDATE 2
The clean query (not tested):
SELECT e.name
,d.cod_team
,d.cod_challenge
,d.title
,d.details
,d.score
,de.proof
,de.date_concluded
,de.cod_challenge_team
FROM teams e
INNER JOIN challengeperteam de ON de.cod_teamFk = e.cod_team
INNER JOIN challenges d ON d.cod_challenge = de.cod_challengeFk
WHERE de.status = 0
ORDER BY e.cod_team DESC, de.cod_challenge_team DESC;
Something along the lines of:
$current_team = null;
foreach($challenges as $challenge){
if($current_team != $challenge->team){
$current_team = $challenge->team;
echo $current_team, "\n";
}
echo $challenge->challenge_name, "\n";
}
At a very basic level, ie in the loop, you can just detect if the TEAM A variable is equal to the current (previous) value, and if so, don't print it a second time. This relies on the result set being sorted on the TEAM A column.
However, you can also do this in the SQL query, so if you can provide the current SQL Query, I can explain how you'd update it.
you could store the array results in a multi-dimensional array like so:
$query_Challenges = "SELECT `Team`,`Challenges` FROM YourTable";
$Challenges = mysql_query($query_Challenges, $dbconnection) or die(mysql_error());
$row_Challenges = mysql_fetch_assoc($Challenges);
$challengeResults = array();
do{
if(!array_key_exists($row_Challenges['cod_team'])){
$challengeResults[$row_Challenges['cod_team']] = array();
}
$challengeResults[$row_Challenges['cod_team']][] = $row_Challenges['cod_challenge_team'];
}while($row_Challenges = mysql_fetch_assoc($Challenges));
EDIT
looking at your query statement, the data should be already sorted properly by your ORDER clause, so if you just need not repeatedly print the team as shown in codeblock 2, then something like:
$team = '';
do {
if($team != $row_Challenges['cod_team']){
echo "TEAM $row_Challenges['cod_team']<br/>";
$team = $row_Challenges['cod_team'];
}
echo " - $row_Challenges['cod_challenge_team']<br />";
}while($row_Challenges = mysql_fetch_assoc($Challenges));
you could easily substitute a foreach for the do loop, as long as there is a variable used as the "current team" and an if statement used to say "dont print the next team name unless its different than the current team name"

Categories