SELECTING multiple rows by 2 columns - php

[ POSTS ]
| id | title | class |
|----|----------|-------|
| 1 | 4567 | 2 |
| 2 | 1234 | 1 |
| 3 | 9124 | 1 |
| 3 | 9124 | w |
________________________
How can i SELECT multiple class column values and sort it to be echoed in HTML like
$query = "SELECT * FROM posts WHERE id = :id"
$statment= $conn->prepare($query);
$statment->execute([':id' => $id]);
while($row = $stmt->fetch()){
$title1 = $row['title'] //WHERE THE CLASS IS 1
$title2 = $row['title'] //WHERE THE CLASS IS 2
echo"
<a>$title1</a>
<a>$title2</a>
}
How do specify which title appear by its class? i already used the id but i want to use the class like
$title1 = $row['id'], AND $row['class'] = 1
$title2 = $row['id'], AND $row['class'] = 2
$titleo = $row['id'], AND $row['class'] = w
to sort it while echo or do i have to go
$query = "SELECT * FROM posts WHERE id = :id AND class = 1"
$query = "SELECT * FROM posts WHERE id = :id AND class = 2"
$query = "SELECT * FROM posts WHERE id = :id AND class = 'w'" //FOR STRINGS

I think you are looking for
SELECT * FROM Posts WHERE class in (1,2,'w') ORDER BY class ASC
This will give you all the posts with the class values within the In () statement. It will show each record separately which means you will have two rows for titles which have multiple class values. Since it looks like you want to separate them using PHP that should be ok. Then you can do that in your while loop like:
$classes = array();
while($row = $stmt->fetch()){
if(!isset($classes[$row['class']])){ $classes[$row['class']] = array(); }
$classes[$row['class']][] = $row['title'];
}
This would give you arrays of Titles for each class:
[
1=>[1234,9124]
2=>[4567]
'w'=>[9124]
]
Then you can output them all in order of the class or by class:
foreach($classes as $key => $class){
echo "Class Value: ".$key; // just to show the order
foreach($class as $title){ echo "<a>".$title."</a>"; }
}
Which will wind up giving you:
Class Value: 1
<a>1234</a>
<a>9124</a>
Class Value: 2
<a>4567</a>
Class Value: w
<a>9124</a>
I am not entirely sure if this leads you to what you are looking for, however, it does give you a workflow to be able to order the posts by class and output them based on class. I hope this helps

Related

PHP Compare column values and edit database accordingly

I am a newbie to PHP and I am stuck at a certain point. I tried looking up a solution for it however, I didn't find exactly what I need.
My goal is to create a leaderboard, in which the values are displayed in descending order plus the rank and score are displayed. Furthermore, it should also display whether or not a tie is present.
The database should look like this:
+---------+------+----------------+-------+------+
| user_id | name | email | score | tied |
+---------+------+----------------+-------+------+
| 1 | SB | sb#gmail.com | 1 | 0 |
+---------+------+----------------+-------+------+
| 2 | AS | as#web.de | 2 | 0 |
+---------+------+----------------+-------+------+
| 3 | BR | br#yahoo.com | 5 | 1 |
+---------+------+----------------+-------+------+
| 4 | PJ | pj#gmail.com | 5 | 1 |
+---------+------+----------------+-------+------+
And the outputted table should look something like this:
+------+-------------+-------+------+
| rank | participant | score | tied |
+------+-------------+-------+------+
| 1 | BR | 5 | Yes |
+------+-------------+-------+------+
| 2 | PJ | 5 | Yes |
+------+-------------+-------+------+
| 3 | AS | 2 | No |
+------+-------------+-------+------+
| 4 | SB | 1 | No |
+------+-------------+-------+------+
I managed to display the rank, participant and the score in the right order. However, I can't bring the tied column to work in the way I want it to. It should change the value, whenever two rows (don't) have the same value.
The table is constructed by creating the <table> and the <thead> in usual html but the <tbody> is created by requiring a php file that creates the table content dynamically.
As one can see in the createTable code I tried to solve this problem by comparing the current row to the previous one. However, this approach only ended in me getting a syntax error. My thought on that would be that I cannot use a php variable in a SQL Query, moreover my knowledge doesn't exceed far enough to fix the problem myself. I didn't find a solution for that by researching as well.
My other concern with that approach would be that it doesn't check all values against all values. It only checks one to the previous one, so it doesn't compare the first one with the third one for example.
My question would be how I could accomplish the task with my approach or, if my approach was completely wrong, how I could come to a solution on another route.
index.php
<table class="table table-hover" id="test">
<thead>
<tr>
<th>Rank</th>
<th>Participant</th>
<th>Score</th>
<th>Tied</th>
</tr>
</thead>
<tbody>
<?php
require("./php/createTable.php");
?>
</tbody>
</table>
createTable.php
<?php
// Connection
$conn = new mysqli('localhost', 'root', '', 'ax');
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// SQL Query
$sql = "SELECT * FROM names ORDER BY score DESC";
$result = $conn->query("$sql");
// Initalizing of variables
$count = 1;
$previous = '';
while($row = mysqli_fetch_array($result)) {
$current = $row['score'];
$index = $result['user_id']
if ($current == $previous) {
$update = "UPDATE names SET tied=0 WHERE user_id=$index";
$conn->query($update);
}
$previous = $current;
?>
<tr>
<td>
<?php
echo $count;
$count++;
?>
</td>
<td><?php echo $row['name'];?></td>
<td><?php echo $row['score'];?></td>
<td>
<?php
if ($row['tied'] == 0) {
echo 'No';
} else{
echo 'Yes';
}
?>
</td>
</tr>
<?php
}
?>
I think the problem is here
$index = $result['user_id'];
it should be
$index = $row['user_id'];
after updating tied you should retrieve it again from database
So I solved my question by myself, by coming up with a different approach.
First of all I deleted this part:
$current = $row['score'];
$index = $result['user_id']
if ($current == $previous) {
$update = "UPDATE names SET tied=0 WHERE user_id=$index";
$conn->query($update);
}
$previous = $current;
and the previous variable.
My new approach saves the whole table in a new array, gets the duplicate values with the array_count_values() method, proceeds to get the keys with the array_keys() method and updates the database via a SQL Query.
This is the code for the changed part:
// SQL Query
$sql = "SELECT * FROM names ORDER BY score DESC";
$result = $conn->query("$sql");
$query = "SELECT * FROM names ORDER BY score DESC";
$sol = $conn->query("$query");
// initalizing of variables
$count = 1;
$data = array();
// inputs table into an array
while($rows = mysqli_fetch_array($sol)) {
$data[$rows['user_id']] = $rows['score'];
}
// -- Tied Column Sort --
// counts duplicates
$cnt_array = array_count_values($data);
// sets true (1) or false (0) in helper-array ($dup)
$dup = array();
foreach($cnt_array as $key=>$val){
if($val == 1){
$dup[$key] = 0;
}
else{
$dup[$key] = 1;
}
}
// gets keys of duplicates (array_keys()) and updates database accordingly ($update query)
foreach($dup as $key => $val){
if ($val == 1) {
$temp = array_keys($data, $key);
foreach($temp as $k => $v){
$update = "UPDATE names SET tied=1 WHERE user_id=$v";
$conn->query($update);
}
} else{
$temp = array_keys($data, $k);
foreach($temp as $k => $v){
$update = "UPDATE names SET tied=0 WHERE user_id=$v";
$conn->query($update);
}
}
}
Thank you all for answering and helping me get to the solution.
instead of the update code you've got use something simular
$query = "select score, count(*) as c from names group by score having c > 1";
then you will have the scores which have a tie, update the records with these scores and your done. Make sure to set tie to 0 at first for all rows and then run this solution
UPDATE for an even faster solution sql based:
First reset the database:
$update = "UPDATE names SET tied=0";
$conn->query($update);
All records have a tied = 0 value now. Next update all the records which have a tie
$update = "update docs set tied = 1 where score IN (
select score from docs
group by score having count(*) > 1)";
$conn->query($update);
All records with a tie now have tied = 1 as we select all scores which have two or more records and update all the records with those scores.

How to retrieve liker id based on ques_id?

Here is my database:
id | liker | ques_id
1 | 15 | 2342
2 | 22 | 2342
3 | 22 | 2311
4 | 15 | 2389
What I need to get is all the liker's who have liked ques_id. So the result should look something like this:
Question 2342 has been liked by 15 and 22.
Question 2311 has been liked by 22 and so on
My current code produces separate row for each liker and ques_id:
$sqlq=mysql_query("SELECT * FROM likes");
while($rowq=mysql_fetch_array($sqlq)){
$qid=$rowq['ques_id'];
$sql=mysql_query("SELECT * FROM likes where ques_id='$qid'");
$num=mysql_num_rows($sql);
$cont='';
while($row=mysql_fetch_array($sql)){
$liker=$row['liker'];
$cont .="$qid being liked by $liker<br>";
}
echo $cont;
}
I haven't tested this but it should get you started:
$sqlq=mysql_query("SELECT DISTINCT(ques_id) FROM likes");
$cont='';
while($rowq=mysql_fetch_array($sqlq)){
$qid=$rowq['ques_id'];
$sql=mysql_query("SELECT * FROM likes where ques_id='$qid'");
$num=mysql_num_rows($sql);
$row=mysql_fetch_array($sql)
$cont .= "$qid being liked by $liker ";
while($row=mysql_fetch_array($sql)){
$liker=$row['liker'];
$cont .= " and $liker";
}
$cont .= ".<br>";
}
echo $cont;
You need no second query to DB, it enough iterate only first result.
For example, you may collect all the likers, that match a specific ques_id in a assoc array with keys are ques_id, like this:
$mathces = array();
$sqlq=mysql_query("SELECT * FROM likes");
while($rowq=mysql_fetch_array($sqlq)){
$qid=$rowq['ques_id'];
$liker=$rowq['liker'];
$matches[ $qid ][] = $liker;
}
Then, you may foreach $mathces array and build you string.
foreach ($matches as $qid => $likers) {
$cont .= "$qid being liked by " . implode(' and ', $likers );
if (count($likers) == 1)
$cont .= ' and so on';
echo "$cont<br>";
}
I didn't test my code. It need to additional validations (e.g. for $linkers in second loop)
SELECT GROUP_CONCAT(liker), ques_id FROM likes GROUP BY ques_id
That will pull each liker grouped together for each ques_id.
You then only have to process the rows returned.
You should steer clear of the mysql extension as it is deprecated; use PDO or mysqli instead.
$sql = 'SELECT GROUP_CONCAT(liker) as likes, ques_id FROM likes GROUP BY ques_id';
foreach ($conn->query($sql) as $row) {
printf('Question %s is liked by %s', $row['ques_id'], $row['likes']);
}

Include corresponding data from table to json from another table

I have two tables-food and tags. Each row from food has corresponding tags.
I want to output each row with those tags, ie:
table food:
id | name
1 | bread
2 | meat
table tags:
reference_id | tag
1 | bakery
1 | wheat
2 | cow
desired output is:
{"results":
[{"id":"1","name":"bread","tags":["bakery","wheat"]},
{"id":"2","name":"meat","tags":["cow"]}]
}
So far I have this:
$db = getConnection();
$stmt = $db->query($sql);//get every column from every food
$food = $stmt->fetchAll(PDO::FETCH_OBJ);
$tagsSql="select id_reference,tag FROM tags T,food F WHERE F.id=T.food_id_reference";
$stmt = $db->query($tagsSql);
$tags=$stmt->fetchAll(PDO::FETCH_OBJ);
echo '{"results":' . json_encode($food) . '}';
I was thinking about cycling through every food and ever tag and find matching pairs, but it seems pretty heavyweight to me (considering the fact, that I could have thousands of rows). Do you have any suggestions?
Untested but I think something like this should work for you
$db = getConnection();
$stmt = $db->query($sql);//get every column from every food
$tagsSql="select F.id as id, F.name as name, group_concat(T.tag SEPARATOR ',') as tags FROM tags T,feeds F WHERE F.id=T.feed_id_reference group by feed_id_reference";
$stmt = $db->query($tagsSql);
for($x = 0; $x < count($tags); $x++){
$tags[$x]->{"tags"} = explode(",", $tags[$x]->{"tags"});
echo '{"results":' . json_encode($tags) . '}';
}

PHP tree menu, bottom-up

I'm having some issues getting a tree menu to work from bottom-up.
I already have a script to work from top-down, which works fine.
This is a very simplified version of my table:
+-----+-----------+--------------------+
| uid | parent_id | page_address |
+-----+-----------+--------------------+
| 1 | 0 | index.php |
| 2 | 0 | login.php |
| 3 | 2 | dashboard.php |
| 4 | 3 | bookings.php |
| 5 | 3 | documents.php |
| 6 | 4 | changebookings.php |
| 7 | 4 | activities.php |
+-----+-----------+--------------------+
The page_address field is unique.
I can work out what page the user is currently on, for example changebookings.php
I would then like a menu to look like this:
login.php
dashboard.php
bookings.php
changebookings.php
activities.php
documents.php
However, the closest I've got so far is the following tree:
login.php
bookings.php
changebookings.php
As you can see, my script currently only returns the actual parent, and not a list of links currently in the parent.
For those interested, the script I use in total is at the bottom of this post.
Is there any easier way to get the bottom-up tree as required?
Many thanks
Phil
EDIT:
I've finally got the code to work, for future users who stumble upon this post, I have added the functionality below:
$dataRows = $databaseQuery->fetchAll(); // Get all the tree menu records
$dataRows = $result->fetchAll(PDO::FETCH_ASSOC);
foreach($dataRows as $row)
{
if($row['link_address']==substr($_SERVER['PHP_SELF'], 1, strlen($_SERVER['PHP_SELF'])-1))
{
$startingId = $row['parent_id'];
}
}
$menuTree = $this->constructChildTree($dataRows, $startingId);
private function constructChildTree(array $rows, $parentId, $nesting = 0)
{
$menu = array();
if(!in_array($nesting, $this->nestingData))
{
$this->nestingData[] = $nesting;
}
foreach($rows as $row)
{
if($row['parent_id']==$parentId && $parentId!=0)
{
$menu[] = $row['link_address'];
$newParentId = $this->getNextParent($rows, $row['parent_id']);
$parentChildren = $this->constructChildTree($rows, $newParentId, ($nesting+1));
if(count($parentChildren)>0)
{
foreach($parentChildren as $menuItem)
{
$menu[] = 'NESTING' . $nesting . '::' . $menuItem;
}
}
}
}
return $menu;
}
private function getNextParent($rows, $parentId)
{
foreach($rows as $row)
{
if($row['uid']==$parentId)
{
return $row['parent_id'];
}
}
}
Without reading your code you should be doing:
1) Get current page, look at parent ID.
2) Load all with that parent ID.
3) Get next Parent ID using current Parent ID as ID.
4) If new parent ID != 0, goto step 2 passing in the new Parent ID.
Sounds like you just need to edit your script to include ALL pages with the given ID as their parent ID.
<?PHP
$sql = "SELECT * FROM TABLE WHERE table parent_id=0";
$result = mysql_query($sql);
while($perant_menu = mysql_fetch_array($result))
{
echo display_child($perant_menu["uid"],$perant_menu["page_address"]);
}
// Recursive function
function display_child($parent_id,$name)
{
$sql= "SELECT * FROM table where parent_id = $parent_id";
$result = mysql_query($sql);
if(mysql_num_rows($result)>0)
{
while($menu = mysql_fetch_array($result))
{
echo display_child($menu["id"],$menu["page_address"]);
}
}
else
{
echo $name;
}
}
?>

Querying results by categories and displaying everything as list

I've a table, basically its something like
------------------
id | name | type
------------------
1 | name1 | type1
2 | name2 | type2
3 | name3 | type3
------------------
I would like to query it and display it into something like
type1
- name1
- and so on...
type2
- name2
- and so on...
type3
- name 3
- and so on...
I am also looking to display it as a JSON file which is something like
[
{
"type1": {
"name": "name1"
},
"type2": {
"name": "name2"
},
"type3": {
"name": "name3"
}
}
]
So, may I know the best way to do it?
Using loops to query the type, then selecting the categories and displaying it by type?
Edit :
After searching high and low in the internet. I've found this : http://www.tommylacroix.com/2008/09/10/php-design-pattern-building-a-tree/
Hence formulated this code for my needs. Not sure if it's efficient :
<?php
$query = "SELECT * FROM TABLE";
$list = array();
$result = mysql_query($query);
while($row = mysql_fetch_array($result)){
if(!$list[$row['type']])
{
$list[$row['type']] = array();
}
array_push($list[$location['type']],&$row['name']) ;
}
?>
Try This.... also see the result output below
SELECT id,CONCAT_WS(',',type,name) as result FROM table GROUP BY id
<?php
$sql= mysql_query("SELECT id,CONCAT_WS(',',type,name) as result FROM table GROUP BY id");
$data = array();
$i=0;
while($row = mysql_fetch_array($sql)){
$ex_res = explode(",",$row['result']);
$data[$ex_res[0]]['name'] = $ex_res[1];
$i++;
}
$a = json_encode($data);
print_r($a);
?>
Result Output
{"type1":{"name":"name1"},"type2":{"name":"name2"},"type3":{"name":"name3"}}

Categories