How can i display Mysql entries in a specific order - php

In my android app i am trying to view a list of friends in the order of who is online and who is not
The code i am using to do it is extracting the request flag (1) from friends table and then use the friend_id to get data from users table and use json_encode to send data back to app in order to display it , the order of friends is displayed in the same order they are in users table :
Here is the code :
if(isset($_POST['list_friends'])) {
$sql = "SELECT friend_id FROM friends WHERE user_id='$user_id' && request='1'";
$res = mysqli_query($connection,$sql) or die(mysqli_error());
$row_to_json = array();
while($rows = mysqli_fetch_assoc($res)) {
foreach($rows AS $row) {
$sql2 = "SELECT * FROM users WHERE id='$row'
ORDER BY FIELD(is_online,'1') DESC";
$res2 = mysqli_query($connection,$sql2) or die(mysqli_error());
while ($rows2 = mysqli_fetch_assoc($res2)) {
//echo $rows_to_json = json_encode((object)$rows2);
$row_to_json[] = (($rows2));
}
}
}
echo json_encode(($row_to_json));
}
is_online field is either (0 if offline and 1 if online)
Any idea of what is wrong in this code ?
EDIT 1 :
I tried this code :
SELECT
friends.friend_id,users.is_online
FROM friends INNER JOIN users ON friends.user_id = users.id
WHERE
(friends.user_id = 21 and request = 1)
ORDER BY
(users.is_online) DESC
I added users.is_online to check for the actual output of this field and this is what is got :
Note that the actual is_online value exists in users table for **22** and
**27** is **0** not **1** !
EDIT 2 :
**
Perfect :)
**

I agree with #Fahad Anjum's comment in that && is very unusual as AND operator in a WHERE condition. Having said this:
1) You could leave away the FIELD() function completely, i.e. write is_online instead of FIELD(is_online, '1').
2) You are using strings where numbers would be sufficient (e.g. user_id = '$user_id' instead of user_id = $user_id). This might be worrying and might cost performance due to implicit casts MySQL might have to do in those cases, and when it comes to the FIELD() function, might be the problem.
The MySQL documentation states:
If all arguments to FIELD() are strings, all arguments are compared as
strings. If all arguments are numbers, they are compared as numbers.
Otherwise, the arguments are compared as double.
In your FIELD() function, you have a mixture of string ('1') and number (is_online) arguments (you have stated that 0 and 1 are possible values of is_online, i.e. is_online contains a number).
I am asking myself what happens when MySQL compares the string '1' with the number 1 after having converted both of them to double, or if something bad happens during the conversion. Theoretically, it should not be a problem because converting a number to double should give the same result as converting that stringified number to double, and because 1 can be represented exactly as a double, but I could imagine that we have a problem here. Unfortunately, I can't test it right now, but you could try writing FIELD(is_online, 1) instead of FIELD(is_online, '1').
3) The main problem is: In your first query, you select friends of the user with the given $user_id. Then you are looping through these friends and for every friend are executing a query against the user table to find out if that user (friend) is online.
That second query returns exactly one row each time; therefore, ordering is useless here.
You will have to solve this problem by doing a join between the friends and the users table in the first place.
Since I have never used PHP, I am a bit reluctant to suggest code here (I don't want to make a fool of myself by publishing code in a language I know nothing about without even being able to test). But your query would resemble the following:
SELECT
friends.friend_id
FROM
(friends INNER JOIN users ON friends.friend_id = users.id)
WHERE
(friends.user_id = $user_id)
ORDER BY
(users.is_online DESC)
Please note that I have left away your second condition here (request = '1') because I can't imagine what it means and it is not that relevant here. You can easily re-add it to the code above.

Related

Is there a more eloquent way of doing these MySQL queries?

I'm making 4 individual queries to a MySQL DB, all of which are identical except the WHERE parameters. 2 of which are:
$totalInvites = mysqli_num_rows(mysqli_query($con, "SELECT code FROM invites"));
$usedInvites = mysqli_num_rows(mysqli_query($con, "SELECT code FROM invites WHERE used IS NOT NULL"));
Is there a way of doing the $totalInvites query and from the returned table, do the WHERE call without doing another query?
If that's confusing, this is an example of what I mean:
$query = mysqli_query($con, "SELECT code FROM invites");
$totalInvites = mysqli_num_rows($query);
$usedInvites = mysqli_num_rows($query /*WHERE used IS NOT NULL*/);
I know that's not proper syntax but that's what I was trying say.
If you just want counts then retrieving the entire database and throwing out the results is not really a good idea. Instead jus task for a count:
SELECT COUNT(*) AS count, used
GROUP BY used
This will give you up to two rows, one count for those that are used and one that isn't presuming used has only NULL or a single non-null value.
Use as little SQL as possible:
SELECT if(used is null, 0, 1) AS used, code
FROM invites
And parse result in PHP according to what you need
SELECT
(SELECT code FROM invites) total
(SELECT code FROM invites WHERE used IS NOT NULL) used

Select data from one table, arrange by a sum of data from another

A client is looking for a points system to be implemented on her website, I'm struggling to display the users based upon the amount of points collected, I hope somebody may be able to help me out here and point me in the right direction to getting this code to work properly.
I am selecting all data from ap_users and in the code I am also trying to select all data from ap_points although I do not require all the data from either tables, to be specific I only require:
ap_users:
user_id
first_name
last_name
display_img
hub_access
ap_points:
user_id
points_added
I thought that selecting ALL data may be the easiest route, will let you decide.
I am trying to select and display all users where hub_access = '1' and order by the total points_added by highest first. Points are added separately by rows and need to be added up (which is why I have the sum function).
$sql = "SELECT * FROM `ap_users`, `ap_points` WHERE `hub_access` = '1' ORDER BY sum(points_added) DESC";
I also tried configuring it to be specific tables like:
ap_users.hub_access and ORDER BY sum(ap_points.points_added) but these did not work either.
This current code is either showing no results or a single result with no errors displaying? I'm not sure whether I may need to use some kind of Group By function to connect the user_ids from both tables ?
SUM is an aggregating function. You should be grouping by user_id if you want the sum for each user_id.
Something like
SELECT *, sum(points_added) as sum_points FROM app_users
JOIN app_points ON app_users.user_id = app_points.user_id
WHERE `hub_access` = '1'
GROUP BY app_users.user_id
ORDER BY sum_points;
I have not tested that query, but that should give you an idea of the solution.

Doubtful about what type of JOIN on MySQL

I'm currently developing a basic web application (using MySQL and PHP). Its goal is to let me and my colleagues (and also those working in different departments) find, change and arrange work shifts. I have two tables:
Users
Shifts
Using the userId column in both tables in order to link them.
When a user looks for a different shift, the query is something like this:
SELECT
s.date,
u.lastname,
s.shift_to_give,
s.seeked_shift,
s.notes,
s.insert_date
FROM
users AS u INNER JOIN shifts AS s
ON
u.userId = s.userId
WHERE
s.shift_to_give = '$shift_to_give'
AND
(*) u.office = (
SELECT
office
FROM
users
WHERE
employee_number = '$employee_number' )
AND
(**) s.status != '1'
AND
s.date='$date'
AND
(***) s.userId != (
SELECT
userId
FROM
users
WHERE
employee_number = '$employee_number' );
The parameters I want to take care of are:.
Each user can obviously see the shifts requests pertaining to his own office (The employee number is already stored with the session from the login.
The "status" column is a flag for making out requests that have already been processed
In search mode each user doesn't see his own requests.
With this statement I have results even when I shouldn't be supposed to.
(if($r) is always true)
How could I do to make it work properly?
After this query, the code continues like so:
$result = mysqli_query($dbc,$query);
if ($result) // If there are results
{
echo "There are x records found..";
mysqli_free_result($result);
mysqli_close($dbc);
}
else
{
echo "No results :-(";
}
If I have any results with my query they are correctly displayed (by checking manually into the db) BUT it never goes to the "else" statement, even when I look for something that doesn't exist...instead, I see a blank page.
Any suggestions?
Meanwhile, thanks for replying so far :-)

Get PHP MySQL PDO column table name as a result of a join [duplicate]

This question already has answers here:
How to resolve ambiguous column names when retrieving results?
(11 answers)
Closed 2 years ago.
I have fields that have the same name in different tables that I'm joining. Such as ticket.status, user.status and transaction.status. At the moment the query returns just status.
How can I get the table name in such a way that it stops similar field names from overwriting and so I can tell the difference between the fields.
Simply put:
$data = array($eventId);
$statement = $this->db->prepare("SELECT * FROM ticket, user, transaction
WHERE ticket.eventId = ?
AND ticket.userId = user.userId
AND ticket.transactionId = transaction.transactionId");
$statement->execute($data);
$rows = $statement->fetchAll(PDO::FETCH_ASSOC);
In my research I've found the constant PDO::ATTR_FETCH_TABLE_NAMES that looks like it could help, but I do not know how to implement ( I assume through $statement->setAttribute(); somehow).
I also have concerns that it will not work, as the PHP documentation mentions it is dependent on the driver.
Thanks
Just add new aliases to your select statements
$statement = $this->db->prepare("
SELECT *, ticket.status AS ticket_status, user.status AS user_status, transaction.status AS transaction_status
FROM ticket, user, transaction
WHERE ticket.eventId = ?
AND ticket.userId = user.userId
AND ticket.transactionId = transaction.transactionId
");
Then you can do
$rows[0]['user_status'];
$rows[0]['ticket_status'];
$rows[0]['transaction_status'];
If you are really concern by performance, the quantity of data returned will be greater so instead of adding new aliases you can select every single columns and while you do so put an alias on the status column.
Why not change your to actually join instead:
SELECT
t.status as ticket_status, u.status as user_status, tr.status as trans_status
FROM
ticket as t
inner join user as u on t.userId = u.userId
inner join transaction as tr on t.transactionId = tr.transactionId
where
t.eventId = ?
You don't even need to cast the tables using as something but I find it's neater.
Note, its the casting of the columns that will actually fix this issue, not the join method.
The most obvious comment is "don't do it, that's why aliases exist". But there's still a good underlying question: does MySQL send information about where a result-set column comes from (table, view or calculated)?
Apparently, it does, since the PDOStatement object has an experimental method called getColumnMeta(). I've been testing and it returns an associative array where the table key
contains the source table if column comes from a table or view
is an empty string if the column is calculated
Of course, I'd stick to aliases anyway. Being able to use associative arrays is a killer feature for me.

Counting occurences in second table compared to first

I have two tables, one holds the information of contributors to my site and one holds information on photographs contributed.
For the admin side of the site, I want to create a table using php and mysql that displays all contributors but also counts the number of photographs each contributor has available for the site.
I get the list of names using this code
SELECT *
FROM site_con
ORDER BY surn ASC
I have then set up a loop to list all the names but have added a query within that loop to count the number of photographs using this code
$contributor = $row_rsContrib['con_Code'];
mysql_select_db($database_connGrowl, $connGrowl);
$query_rsCounter = "SELECT COUNT(*) AS Count
FROM site_phts
WHERE photter = $contributor";
$rsCounter = mysql_query($query_rsCounter, $connGrowl) or die(mysql_error());
$row_rsCounter = mysql_fetch_assoc($rsCounter);
$totalRows_rsCounter = mysql_num_rows($rsCounter);
The only problem is when '$contributor' is not in the photographs table, it returns an error.
Any ideas?
You can get the list of contributors & the number of photos in a single query:
SELECT sc.*,
COALESCE(x.numPhotos, 0) AS numPht
FROM SITE_CON sc
LEFT JOIN (SELECT sp.photter,
COUNT(*) AS numPhotos
FROM SITE_PHTS sp
GROUP BY sp.photter) x ON x.photter = sc.con_code
ORDER BY ssc.surn
Your query fails because a photographer doesn't necessarily have contributions -- the query above returns the list of photographers, and those without photos associated will have a numPht value of zero. Here's a primer on JOINs, to help explain the OUTER JOIN that's being used.
Actually the best way to do this is by using MSQL to count rather than PHP:
SELECT site_con.*, COUNT( photo_id )
FROM site_con
LEFT JOIN site_phts ON site_con.con_Code = site_phts.photter
GROUP BY site_con.con_Code
ORDER BY site_con.surn
The LEFT JOIN has the special property of creating NULL entries when there is no row in the right table (photos) that matches a contributor row. COUNT will not count these NULL entries. (You need some unique column in the photos table, I used photo_id for that.)
this is the relation between Contributors and photographs:
1 photograph can have a most 1 Contributor
1 Contributor can have a most infinit photograph
Contributor <-(0,n)------(0,1)-> Photograph
so you might wanna add a connexion betweet those two tables, I mean you add the con_id to the photographs table (as a column).
this way you'll be able to retrieve all the informations in one SQL query.
(like OMG Ponies just said)
Do something like this, I believe this should work :
$result = mysql_query("SELECT COUNT(*) AS Count FROM site_phts WHERE photter = '$contributor'"); // put the single quote if $contributor is a string value
//use mysql_fetch_array
if ($row = mysql_fetch_array($result, MYSQL_NUM)) {
printf("ID: %d", $row[0]);
}
Hopefully this works, Good luck mate !

Categories