check for multiple values count - php

i need to check if in an exam that contains 5 students
exist 3 students from the same class.
here is what i tried
<?
//this array contains all student id's that are in an exam
$exam = array('s1' => $s1, 's2' => $s2, 's3' => $s3, 's4' => $s4, 's5' => $s5);
$values = implode(", ", $exam);
$sql = "SELECT class FROM students WHERE students.id IN (" . $values . ")";
try{
$db = new db();
$db = $db->connect();
$stmt = $db->query($sql);
$studs = $stmt->fetchAll(PDO::FETCH_ASSOC);
$db = null;
if(!empty($studs)) {
//check if 3 students from the same class are taking the exam
$i = 0; $s = 0;
foreach($exam as $e )
{
if( !in_array( $e, $studs[$i] ) )
{
$exist = FALSE;
}
else {$s++;}
$i++;
}
if ($s<=3) {
#do sth
}
else {
echo "more than 3 students";
}
} else {
echo "error";
}
} catch(PDOException $e) {}
?>
Problem
what i am not sure about is how to count that 3 students have the same class id in this exam array.
i know there is something i need to fix in my foreach just trying with no success.

You can ask your database to return all classes with 3 or more students from your id list by applying an an aggregate snd grouping your results by the class ánd using a HAVING clause:
SELECT class, COUNT(id) as num_students_in_class FROM students WHERE id IN (1,2,3,4) GROUP BY class HAVING COUNT(id) >= 3
More info:
How to use group by in SQL Server query?
What's the difference between HAVING and WHERE?

If you dont want to query as suggested in https://stackoverflow.com/a/46517195/100809 you’ll need to keep an assoc array of the classes and the number of times you’ve seen it:
$seenClasses = array_count_values($studs);
foreach($seenClasses as $class => $numStudents) {
if ($numStudents > 4)
echo “class $class has $numStudents”;
}

Related

how to count members in 15 level deep for each level in php

I am badly in need of counting every member on each level I have 15 level deep Commission model so I am able to count the first level but not able to count the whole team a person have in his / her down line. I want to count how many members on each level.
like on 1st level 10 members, second level 55 members, third level 35 members etc.
I need to count the whole number of members for Parent id on 1st level, 2nd level ... up to 15th level.
I am able to count on the first level like
$result = mysqli_query($con, "SELECT count(*) FROM affiliateuser where referedby = '" . $_SESSION['username'] . "' AND active = 1");
if you need any clarification please comment I will explain.
I am sharing my first 2 Level code here. Please check the code below.
started Fetching 1st level of downline users
$totalref = 0;
$totalrefear = 0;
$query = "SELECT fname,email,doj,active,username,level,pcktaken FROM affiliateuser where referedby = '" . $_SESSION['username'] . "'";
$result = mysqli_query($con, $query);
while($row = mysqli_fetch_array($result)) {
$ac = "$row[active]";
$countusername = "$row[username]";
$countuserlevel = "$row[level]";
$pcktook = "$row[pcktaken]";
}
started Fetching 2nd level of downline users
$totalrefear = 0;
$query = "SELECT fname,email,doj,active,level,username FROM affiliateuser where referedby = '" . $_SESSION['username'] . "'";
$result = mysqli_query($con, $query);
while($row = mysqli_fetch_array($result)) {
$ac = "$row[active]";
$countusername = "$row[username]";
$countuserlevel = "$row[level]";
$query2level = "SELECT fname,email,doj,active,level,username,pcktaken FROM affiliateuser where referedby = '$countusername'";
$result2level = mysqli_query($con, $query2level);
while($row2 = mysqli_fetch_array($result2level)) {
$ac2 = "$row2[active]";
$countusername2 = "$row2[username]";
$countuserlevel2 = "$row2[level]";
$pcktook = "$row2[pcktaken]";
}
}
I am trying with this query for counting users in the 2nd level of the parent. But it's counting me whole database users. I just want to count 2nd level users.any body help me solve it, please?
$queryridd =mysqli_query($con, "SELECT COUNT(Id) AS countt, level AS Lebel from affiliateuser WHERE level = '$countuserlevel' GROUP BY level");
Assuming that you have a parent_id field, you count how many records have parent_id equal to the one you're looking at. To get the next level down, you just repeat for each of the records you just got.
Now... how do you do that?
First, your database needs to be planned correctly. There are many ways to make a tree structure, from the simple parent - child using recursion, to materialized path, to nested sets. Each has advantages and disadvantages. I personally like materialized path; but the depth of the tree for your application makes some variation of parent-child more likely.
So what does the database structure look like?
Superheroes
----------
id <--\
parent_id ---/
name
So if you have a hierarchy like so:
1 Steven Rogers
/ \
2 Bruce Banner 3 Wally West
/ \
4 Peter Parker 5 Jay Garrick
/ \
6 Barry Allen 7 Reed Richards
Your table would look like so:
superheroes
-----------
id parent_id name
1 0 Steven Rogers
2 1 Bruce Banner
3 1 Wally West
4 2 Peter Parker
5 2 Jay Garrick
6 4 Barry Allen
7 4 Reed Richards
To find who is directly below Steve Rogers,
$sth = $dbh->prepare("select id,name from superheroes where parent_id=?");
$sth->execute(array(1));
$result = $sth->fetchAll();
To find who is directly below Peter Parker,
$sth = $dbh->prepare("select id,name from superheroes where parent_id=?");
$sth->execute(array(4));
$result = $sth->fetchAll();
So great, that gets one level. How do I get the next level? This is a job for a function. (Actually, a class would be much better, since scope is so much easier to deal with.)
class CountDownLine {
public function __construct($database) {
$this->db = $database;
}
public function getDownline($id, $depth=2) {
$stack = array($id);
for($i=1; $i<=$depth; $i++) {
// create an array of levels, each holding an array of child ids for that level
$stack[$i] = $this->getChildren($stack[$i-1]);
}
return $stack;
}
public function countLevel($level) {
// expects an array of child ids
settype($level, 'array');
return sizeof($level);
}
private function getChildren($parent_ids = array()) {
$result = array();
$placeholders = str_repeat('?,', count($parent_ids) - 1). '?';
$this->$db->prepare("select id from superheroes where parent_id in ($placeholders)");
$this->$db->->execute(array($parent_ids));
while($row=$this->$db->fetch()) {
$results[] = $row->id;
}
return $results;
}
}
Here's how it works:
$DL = new CountDownLine(new Database); // inject your favorite database abstraction
$id = 1; // ie, id of Steve Rogers
$depth = 2; // get the counts of his downline, only 2 deep.
$downline_array = $DL->getDownline($id, $depth=2);
// => $downline_array[1] = [2,3]
// => $downline-array[2] = [4,5]
$count_of_first_level = $DL->countLevel($downline_array[1]);
$count_of_second_level = $DL->countLevel($downline_array[2]);
Note: This is to show the concept. I did not test it on a database. You'll have to adapt it to work with your method of database access.
Please use if to check the levels before proceeding to another level
<?php
$query = "SELECT fname,email,doj,active,level,username FROM affiliateuser where referedby = '" . $_SESSION['username'] . "'";
$result = mysqli_query($con, $query);
while($row = mysqli_fetch_array($result)) {
$ac = "$row[active]";
$countusername = "$row[username]";
$countuserlevel = "$row[level]";
// use if to check the level
if($countuserlevel == 2) { // use if to check the level
$query2level = "SELECT fname,email,doj,active,level,username,pcktaken FROM affiliateuser where referedby = '$countusername'";
$result2level = mysqli_query($con, $query2level);
while($row2 = mysqli_fetch_array($result2level)) {
$ac2 = "$row2[active]";
$countusername2 = "$row2[username]";
$countuserlevel2 = "$row2[level]";
$pcktook = "$row2[pcktaken]";
}
$queryridd = mysqli_query($con, "SELECT COUNT(Id) AS countt, level AS Lebel from affiliateuser WHERE level = '$countuserlevel' GROUP BY level");
while($rowbb = mysqli_fetch_array($queryridd)) {
$countingUsers2 = "$rowbb[0]";
}
}
} // use if to check the level
?>
<td class='text-left'><?php echo $countingUsers2; ?></td>
You can easily get the number of children per level for a given user.
<?php
/*
* $parent_id = ID of user
* $deep = amount of depth levels
*/
function countChildrenPerLevelDeep( $parent_id, $deep = 15 ) {
$parent_id = [$parent_id];
$level = 1;
$arr = [];
$i = 1;
do {
if ( $parent_id ) {
$query = 'SELECT * FROM customer WHERE parent_id=' . implode( $parent_id, ',' );
if ( $result = $mysqli->query( $query ) ) {
/* total children on this level */
$arr['level_' . $level] = $result->fetch_row();
$parent_id = [];
/* fetch associative array */
while ( $row = $result->fetch_assoc() ) {
$parent_id[] = $row['id'];
}
/* free result set */
$result->close();
} else {
$arr['level_' . $level] = 0;
$parent_id = [];
}
} else {
$arr['level_' . $level] = 0;
$parent_id = [];
}
$level++;
$i++;
}
while ( $i <= $deep );
return $arr;
}
?>
Exemple of result
Array
(
[level_1] => 1
[level_2] => 2
[level_3] => 1
[level_4] => 0
[level_5] => 0
[level_6] => 0
)

Make SQL selection from nested arrays

I am trying to make a selection based on a nested array I get from a prior selection.
Here is where I make my first selection:
$coursequery = "
SELECT
courseID
FROM enrollments
WHERE
studentID = '$userid'
";
try
{
$stmt = $db->prepare($coursequery);
$result = $stmt->execute();
}
catch(PDOException $ex)
{
die("Failed to run query: " . $ex->getMessage());
}
$rows = $stmt->fetchAll();
$_SESSION['studentcourses'] = $rows;
This gets all the courseID's in the following format:
Array ( [0] => Array ( [courseID] => 6 ) [1] => Array ( [courseID] => 7 ) )
and I want to be able to access these ID's for selecting information from a different table. I've started by trying to use a for loop to grab all the "course information" depending on the ID.
for($i = 0; $i < $count; $i++) {
$coursequery = "
SELECT
*
FROM courses
WHERE courseID = '$studentcourses[$i]'
";
try
{
$stmt = $db->prepare($coursequery);
$result = $stmt->execute();
}
catch(PDOException $ex)
{
die("Failed to run query: " . $ex->getMessage());
}
$row = $stmt->fetchAll();
$_SESSION['studentcourseinfo'] = $row;
}
Any help would be greatly appreciated in accomplishing this!
You can accomplish this with one SQL query thus eliminating all these loops
SELECT
*
FROM courses
INNER JOIN enrollments ON
enrollments.courseID = courses.courseID
AND enrollments.studentID = '$userid'
WHERE 1
you can use same array in query, can use implode function
$coursequery = "SELECT * FROM courses
WHERE courseID IN (" . implode(",", $studentcourses) . ");";
As long as you change the output format
Array (6, 7)
where 6 and 7 would be the id of the courses
Also in you code have mistake in rewrite var $_SESSION['studentcourseinfo'] = $row; these overwriting the same variable at a time

Match Where Multiple Columns are... PHP PDO

I have a search query which works, but not the way I had hope. Here:
try{
/*
Create Search Query.
*/
//Include database config file.
include('config.php');
//Get values from Angular.
$valuesPost=$_POST;
$values=array();
foreach ($valuesPost as $rows) {
$decodedValues=json_decode($rows, TRUE);
$values[]=$decodedValues;
}
//Get table from post values.
$table=$values[0]["table"];
//Get limit from post values.
$limit=$values[0]["limit"];
//Get offset from post values.
$offset=$values[0]["offset"];
//Get orderBy from post values.
$orderBy=$values[0]["orderBy"];
//Unset Whole array
unset($values[0]);
//Create cats fields
$cats=array_keys($values[1]);
if(empty($cats)) {
$cats = null;
} else {
foreach($cats as &$val){
$val="cat_id = :".$val;
}
$cats=implode(" OR ", $cats);
}
//Create subCats fields
$subCats=array_keys($values[2]);
if(empty($values[2])) {
$subCats[0] = null;
} else {
foreach($subCats as &$val){
$val="sub_cat_id = :".$val;
}
$subCats=implode(" OR ", $subCats);
}
//Create colourCats fields
$colourCats=array_keys($values[3]);
if(empty($colourCats)) {
$colourCats[0] = null;
} else {
foreach($colourCats as &$val){
$val="colour_id = :".$val;
}
$colourCats=implode(" OR ", $colourCats);
}
$where = "";
//Create Where Statement
if(empty($cats[0]) && empty($subCats[0])){
$where = $colourCats;
}
if(empty($cats[0]) && empty($colourCats[0])){
$where = $subCats;
}
if(empty($subCats[0]) && empty($colourCats[0])){
$where = $cats;
}
if(empty($colourCats[0]) && !empty($cats[0]) && !empty($subCats[0])){
$where = $cats." AND ".$subCats;
}
if(empty($subCats[0]) && !empty($cats[0]) && !empty($colourCats[0])){
$where = $cats." AND ".$colourCats;
}
if(empty($cats[0]) && !empty($subCats[0]) && !empty($colourCats[0])){
$where = $subCats." AND ".$colourCats;
}
if(!empty($cats[0]) && !empty($subCats[0]) && !empty($colourCats[0])){
$where = $cats." AND ".$subCats." AND ".$colourCats;
}
//Search query.
$search="SELECT * FROM $table WHERE $where ORDER BY $orderBy LIMIT $limit OFFSET $offset";
/*
Database Connection.
*/
//Crate a database connection variable: $conn and error checking attributes.
$conn = new PDO($DB_SETTINGS, $DB_USER, $DB_PASS);
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
/*
PDO WORK.
*/
//SEARCH_LIKE_ALL QUERY!
//Prepare query.
$search_qry=$conn->prepare($search);
//For each array index create array $rows.
foreach ($values as $rows) {
//Bind each value to $value_fields from $rows array.
foreach ($rows as $key => &$value) {
switch(gettype($value)) {
case 'integer':
case 'double':
$search_qry->bindParam(':' . $key, $value, PDO::PARAM_INT);
break;
default:
$search_qry->bindParam(':' . $key, $value, PDO::PARAM_STR);
}
}
}
$search_qry->execute();
$rows = $search_qry->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($rows);
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
It builds the query fine. In my angularjs script I build a multidimensional array where index [0] contains data such as table, orderby and limits. Index [1] contains an array of Categories. Index[2] an array of Sub Categories and Index[3] an array of Colour Categories. My problem is that the search query is bring back data I am not expecting. So lets say I send this type of array:
values[0]={table: table, order_by: prod_code, limit: 10, offset 0}
values[1]={cat_id0: 1};
values[2]={sub_cat_id0: 1, sub_cat_id1: 3}
values[3]={colour_id0: 1, colour_id1: 2}
I want only products in cat 1 with sub cats 2 & 3 and a colour id 1 & 2. It is changing order when I remove a sub cat id from the array but is still in search, I assume this product is later being picked up by a colour id. Is the query wrong or the way in which I am searching.
From the array above:
$search="SELECT * FROM table WHERE cat_id=:cat_id0 AND sub_cat_id=:sub_cat_id0 OR sub_cat_id=:sub_cat_id1 AND colour_id=:colour_id0 OR colour_id=:colour_id1 ORDER BY prod_code LIMIT 10 OFFSET 0"
I think the big problem you have is the order of precedence between AND and OR.
SELECT a
, b
, c
, a OR b AND c
, (a OR b) AND c
FROM ( SELECT 1 AS a UNION SELECT 0 ) a
CROSS
JOIN ( SELECT 1 AS b UNION SELECT 0 ) b
CROSS
JOIN ( SELECT 1 AS c UNION SELECT 0 ) c
WHERE NOT (a.a = b.b AND a.a = c.c)
ORDER BY c, b, a
a b c a OR b AND c (a OR b) AND c
------ ------ ------ ------------ --------------
1 0 0 1 0
0 1 0 0 0
1 1 0 1 0
0 0 1 0 0
1 0 1 1 1
0 1 1 1 1
That is to say
foo = a OR foo = b AND bar = c
is evaluated as:
( foo = a ) OR ( foo = b AND bar = c )
when what you probably want is:
(foo = a OR foo = b ) AND ( bar = c )
I'm having trouble deciphering what the code is doing.
For example, why do you need all those permutations of conditions in building the WHERE clause? Why all those checks? Why not something simpler, like:
$where = " 1=1";
if (!empty($cats[0]) {
$where .= " AND (" . $cats . ")";
}
if (!empty($subCats[0]) {
$where .= " AND (" . $subCats . ")";
}
if (!empty($colourCats[0]) {
$where .= " AND (" . $colourCats . ")";
}
Also, all those OR conditions testing equality
foo = a OR foo = b OR foo = c OR foo = d
Can be expressed much more elegantly using an IN
foo IN (a,b,c,d)
//Create cats fields
$cats=array_keys($values[1]);
if(empty($cats)) {
$cats = null;
} else {
$cats=" cat_id IN (". implode(",",$cats) . ");
}

PHP / MySQL - Query loop?

I have the following function:
private static function getFixedFare($FixedFareId) {
$pdo = new SQL();
$dbh = $pdo->connect(Database::$serverIP, Database::$serverPort, Database::$dbName, Database::$user, Database::$pass);
try {
$query = "SELECT Fare FROM tblfixedfare
WHERE FixedFareId = :fixed_fare_id
AND DayHalf = :day_half";
$stmt = $dbh->prepare($query);
$stmt->bindParam(':fixed_fare_id', $FixedFareId, PDO::PARAM_INT);
$stmt->bindParam(':day_half', self::$day_half, PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_COLUMN);
$stmt->closeCursor();
$dbh = null;
return $result;
}
catch (PDOException $pe) {
die("Error: " .$pe->getMessage(). " Query: ".$stmt->queryString);
}
}
Basically I want to change the query to do nine different selects, as follows:
$query = "SELECT Fare FROM tblfixedfare
WHERE FixedFareId = :fixed_fare_id
AND DayHalf = :day_half
AND CarType = 'Car'";
and
$query = "SELECT Fare FROM tblfixedfare
WHERE FixedFareId = :fixed_fare_id
AND DayHalf = :day_half
AND CarType = 'Est'";
and the same for all the other car types, 'Exec', 'ExecEst', '6B', '7B', '7W', '8B' and 'Bus' which will only ever be these car types.
I was hoping I could store each of these query results into different variables without having to do 9 different queries (reducing code). Such as a loop and then storing the results to $resultcar, $resultest and so on...
Not to sure how I would do this so any help would be much appreciated! :-)
You can do an IN
SELECT CarType, Fare FROM tblfixedfare
WHERE FixedFareId = :fixed_fare_id
AND DayHalf = :day_half
AND CarType IN ('Car', 'Est' ...);
Note that you have to include the CarType in the Select so you can filter them after the query.
UPDATED: You can group your results by CarType already like this:
$results = $stmt->fetchAll(PDO::FETCH_ASSOC|PDO::FETCH_GROUP);
The code above should give you something like:
array(
'Car' => array(
// data
),
'Est' => array(
// data
)
)
If you don't mind changing your variables, you can immediately have them in variables without looping through extract(...)
So feeding
$results = $stmt->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_GROUP);
which is the array mentioned above to extract:
extract($results, EXTR_PREFIX_ALL, 'result');
will let you have the result sets in variables already:
var_dump($result_Car);
array(2) {
[0]=> array(1) {
["Fare"]=> string(1) "100"
}
[1]=>
array(1) {
["Fare"]=> string(1) "200"
}
}
All in all, in one line:
extract($q->fetchAll(PDO::FETCH_ASSOC|PDO::FETCH_GROUP), EXTR_PREFIX_ALL, 'result');
For repeating the query on the nine different car types, you can store each of the car names into an array and loop through the array inserting the new name each time:
$cars = array();
array_push($cars, "Car", "Est", "Exec", "ExecEst", "6B", "7B", "8B","Bus");
for($i=0; $i < sizeof($cars); $i++)
{
try {
$query = "SELECT Fare FROM tblfixedfare
WHERE FixedFareId = :fixed_fare_id
AND DayHalf = :day_half
AND CarType = '".$cars[i]."'";
//.....rest of your code
}
catch (PDOException $pe) {
die("Error: " .$pe->getMessage(). " Query: ".$stmt->queryString);
}
}
You can then store the result of each query in a new array using the name of the car ( i.e $cars[i] ) as the key.

array_intersect within foreach loop

this is my first time posting here, although I have gotten many great tips and techniques reading the posts here.
Here is my objective:
I have 2 somewhat similar tables to compare. For each row of each table, I am pulling the fields I want into into an array.
I basically want to echo out the values of any array from one table that has matching values in the other array.
Here is my code, maybe it will be easier to understand.
$sql = "SELECT * FROM $i_comp ORDER BY `manufacturer`";
$statement = $objDb->query($sql);
$c_skus = $statement->fetchAll(PDO::FETCH_ASSOC);
$sql = "SELECT `sku_one`,`sku_two`,`qty`,`manufacturer`";
$sql .= "FROM $i_gas ORDER BY `manufacturer`";
$statement = $objDb->query($sql);
$d_skus = $statement->fetchAll(PDO::FETCH_ASSOC);
foreach ( $c_skus as $c_sku ) {
// i want to see if any values of this array exist in the array created hy
// the foreach loop below (yes, repeat for each row)
$c = array($c_sku['sku'],$c_sku['sku_one'],$c_sku['sku_two'],$c_sku['sku_three']);
foreach ( $d_skus as $d_sku ) {
$d = array($d_sku['sku_one'],$d_sku['sku_two']);
$intersect = array_intersect($c, $d);
echo '<pre>', print_r($intersect), '</pre>';
}
}
Here are the results I receive for each iteration of the code:
Array
(
)
1
It should also be noted that I am not concerned with the Keys, just the Values. Eventually, those values will be works into an INSERT statement but for the time being I just need to get the right results.
Anyways, thanks for any and all help!
This is usually done in SQL
if you want whole row that has at least 1 matching SKU in another table:
$sql = "
SELECT c.* FROM $i_comp AS c
JOIN $i_gas AS d
ON d.sku_one in (c.sku, c.sku_one, c.sku_two, c.sku_three)
OR d.sku_two in (c.sku, c.sku_one, c.sku_two, c.sku_three)
ORDER BY c.`manufacturer`";
$statement = $objDb->query($sql);
$c_skus = $statement->fetchAll(PDO::FETCH_ASSOC);
// all rows that have at least 1 matching sku on another table
print_r($c_skus);
If you want only SKUs
$sql = "
SELECT d.sku_one FROM $i_comp AS c
JOIN $i_gas AS d
ON d.sku_one in (c.sku, c.sku_one, c.sku_two, c.sku_three)
UNION
SELECT d.sku_two FROM $i_comp AS c
JOIN $i_gas AS d
OR d.sku_two in (c.sku, c.sku_one, c.sku_two, c.sku_three)
";
$statement = $objDb->query($sql);
$c_skus = $statement->fetchAll(PDO::FETCH_ASSOC);
// all skus that have at least 1 matching sku on another table
print_r($c_skus);
In PHP intersect variant you need to build the arrays separately and then use array_intersect
$c = array();
foreach ( $c_skus as $c_sku ) {
$c[] = $c_sku['sku'];
$c[] = $c_sku['sku_one'];
$c[] = $c_sku['sku_two'];
$c[] = $c_sku['sku_three'];
}
$d = array();
foreach ( $d_skus as $d_sku ) {
$d[] = $d_sku['sku_one'];
$d[] = $d_sku['sku_two'];
}
$intersect = array_intersect($c, $d);
echo '<pre>', print_r($intersect), '</pre>';

Categories