how to query mysql database without repeats from one of the fields - php

Here's my current code:
<?php
$tsql = " ";
$tmpsort = " ORDER BY b.flag,b.jjloveb DESC,b.yhtime ";
$rt=$db->query("SELECT a.nickname, a.sex, a.grade, a.photo_s, a.photo_f, a.photo_pass, b.id,b.userid, b.datingkind, b.title, b.price, b.yhtime, b.maidian, b.content, b.bmnum, b.click, b.flag, b.jjloveb, a.birthday, b.province, b.city, b.area, b.age1, b.datingkind, a.identityproof
FROM ".__TBL_MAIN__." a,".__TBL_DATING__." b
WHERE $tsql b.flag>0 AND b.userid=a.id AND a.flag=1
$tmpsort
LIMIT 6");
$total = $db->num_rows($rt);
for($i=0;$i<$total;$i++) {
$rows = $db->fetch_array($rt);
if(!$rows) break;
$Uid = $rows[7];
$Unickname = badstr($rows[0]);
$Usex = $rows[1];
What I want is to fetch the records from the same user id only once.
Thanks very much!

$rt=$db->query("SELECT a.nickname,a.sex,a.grade,a.photo_s,a.photo_f,a.photo_pass,b.id,b.userid,b.datingkind,b.title,b.price,b.yhtime,b.maidian,b.content,b.bmnum,b.click,b.flag,b.jjloveb,a.birthday,b.province,b.city,b.area,b.age1,b.datingkind,a.identityproof FROM ".__TBL_MAIN__." a,".__TBL_DATING__." b WHERE $tsql b.flag>0 AND b.userid=a.id AND a.flag=1 group by b.userid $tmpsort LIMIT 6");
I achieved what I wanted by just inserting a group by. Yeah!
But what about if 2 occurrences per userid is wanted, what approach should be taken?

Related

Creating a subquery with mysqli in PHP to fetch array last 10 results in ascending order

I thought this would be simple but I'm having a tough time figuring out why this won't populate the the data array.
This simple query works fine:
$queryPrice = "SELECT price FROM price_chart ORDER BY id ASC LIMIT 50";
$resultPrice = mysqli_query($conn, $queryPrice);
$data = array();
while ($row = mysqli_fetch_array($resultPrice)) {
$data[] = $row[0];
}
But instead I want it to choose the last 10 results in Ascending order. I found on other SO questions to use a subquery but every example I try gives no output and no error ??
Tried the below, DOESN'T WORK:
$queryPrice = "SELECT * FROM (SELECT price FROM price_chart ORDER BY id DESC LIMIT 10) ORDER BY id ASC";
$resultPrice = mysqli_query($conn, $queryPrice);
$data = array();
while ($row = mysqli_fetch_array($resultPrice)) {
$data[] = $row[0];
}
I also tried specifying the table name again and using the IN, also doesn't work:
$queryPrice = "SELECT price FROM price_chart IN (SELECT price FROM price_chart ORDER BY id DESC LIMIT 10) ORDER BY id";
$resultPrice = mysqli_query($conn, $queryPrice);
$data = array();
while ($row = mysqli_fetch_array($resultPrice)) {
$data[] = $row[0];
}
In both examples my array is blank instead of returning the last 10 results and there are no errors, so I must be doing the subquery wrong and it is returning 0 rows.
The subquery doesn't select the id column, so you can't order by it in the outer query. Also, MySQL requires that you assign an alias when you use a subquery in a FROM or JOIN clause.
$queryPrice = "SELECT *
FROM (SELECT id, price
FROM price_chart
ORDER BY id DESC LIMIT 10
) x ORDER BY id ASC";
$resultPrice = mysqli_query($conn, $queryPrice) or die (mysqli_error($conn));
$data = array();
while ($row = mysqli_fetch_assoc($resultPrice)) {
$data[] = $row['price'];
}
You would have been notified of these errors if you called mysqli_error() when the query fails.
Your second query is the closest. However you need a table alias. (You would have seen this if you were kicking out errors in your sql. Note you will need to add any field that you wish to order by in your subquery. In this case it is id.
Try this:
SELECT * FROM (SELECT price, id
FROM price_chart ORDER BY id DESC LIMIT 10) as prices
ORDER BY id ASC
You must have errors, because your SQL queries are in fact incorrect.
First, how to tell you have errors:
$resultPrice = mysqli_query (whatever);
if ( !$resultprice ) echo mysqli_error($conn);
Second: subqueries in MySQL need aliases. So you need this:
SELECT * FROM (
SELECT id, price
FROM price_chart
ORDER BY id DESC LIMIT 10
) AS a
ORDER BY id ASC";
See the ) AS a? That's the table alias.

From PHP how to efficiently execute this search in SQL Server?

I have a database structure something like the following:
Table A: PersonId, GroupId
Table B: GroupId, ParentGroupId
Given a PersonId, I want to find the Ids of all people in parent groups of that person's group.
First I select the ParentGroupId for the given PersonId, by joining with B. Then I do a while loop, selecting and recording the PersonId from A based on the GroupId returned in the previous search, and continue the loop by obtaining the next ParentGroupId from B.
Is this an efficient way to do this search, or is there an option that does not involve a while to "bubble up" in this manner?
(this is a simplified version of the actual scenario, changing the schema is not an option)
$sql = 'SELECT ParentGroupID FROM A WHERE PersonId = ' . $id;
$result = $db->query($sql);
$row = $db->fetch_array($result);
$parent_group = $row['ParentGroupId'];
if(!is_null($parent_group)) {
$parent_ids = array();
while($parent_group > 0) {
//is there a way to do this where I retrieve all managers <= lvl 6 at once, so I don't have to loop in order to 'tier up'?
$sql = 'SELECT ParentGroupID, PersonID
FROM B
INNER JOIN A on ParentGroupID = A.GroupID
WHERE ParentGroupID = ' . $parent_group;
$result = $db->query($sql);
$row = $db->fetch_array($result);
$parent_group = $row['ParentGroupID'];
$parent_ids[] = $row['PersonID'];
}
}
Combining your two queries into one would be more efficient:
$sql = 'SELECT ParentGroupID, PersonID
FROM B
INNER JOIN A on ParentGroupID = A.GroupID
WHERE ParentGroupID IN (
SELECT ParentGroupID FROM A WHERE ParentGroupID > 0
AND PersonId = ' . $id .')' ;

PHP Sort an array

I have an array
$genreQuery = $con ->query ("select distinct(movie_year) from movies");
$movieGenre = array();
$movieTitle = array();
$movieList = array();
while($row = $genreQuery->fetch_object()) {
$movieGenre[] = $row;
}
foreach($movieGenre as $MGenre){
$query = $con ->query
("
select '$MGenre->movie_year' movie_year, IFNULL(count(*)/(select count(*)
from user_movie_ratings where user_id = '$userid'),0) rating
from user_movie_ratings umr,
movies m
where umr.user_id = '$userid'
and umr.movie_id = m.id
and m.movie_year = '$MGenre->movie_year' ORDER BY rating DESC;
");
while($row = $query->fetch_object()) {
$movieTitle[] = $row;
}
}
$text = "";
foreach($movieTitle as $MTitle){
if (empty($text)){
$text = "\"".$MTitle->movie_year."\"";}
else{
$text = $text.",\"".$MTitle->movie_year."\"";
}
}
$list = $con ->query
("
SELECT movie_name, avg_rating, image, id, genre
FROM movies
WHERE id NOT IN (SELECT movie_id FROM user_movie_ratings WHERE user_id = '$userid')
ORDER BY field(movie_year, $text), avg_rating DESC;
");
while($row = $list->fetch_object()) {
$movieList[] = $row;
}
The array is filled by the above query, what I want to do is sort it by the rating so that is looks like this
year rating
2014 0.0001
2015 0.0000
2013 0.0000
1967 0.0000
.... ......
.... ......
etc etc
I have tried adding ORDER BY rating DESC to the query, but that does not work and when I use rsort($movieTitle) it sorts by the year not the rating do I need to do some kind of multidimensional sort, or is there another way?
I would guess that ordering by rating does not work as you seem to be running multiple queries in a foreach loop and each iteration gets one year. So in that case, your order would be by year and then in the year by rating.
You should get rid of that loop and only do one query and then the condition and sort order would be:
...
AND m.movie_year IN (the,years,you,want)
ORDER BY rating DESC
By looping over the $movieGenre like you do now, you can easily generate a comma separated list for the years to use in the IN statement.
Edit: Based on your comment you want all years, so the foreach loop and the year condition in the query are unnecessary.
You probably want something like:
SELECT m.movie_year, IFNULL(count(*)/(select count(*)
from user_movie_ratings where user_id = '$userid'),0) rating
FROM user_movie_ratings umr,
movies m
WHERE umr.user_id = '$userid'
AND umr.movie_id = m.id
ORDER BY rating DESC
Assuming of course that the user ID is safe to use in a query, you should really use a prepared statement to avoid potential sql injection.
Now you have all your results in one query so there is no need for the outer loop any more.

Is it ok to query inside a while loop?

I have two tables in one database. I am querying the first table limit by 10 then loop the results. And inside the while loop, I am doing again another query using a data from the first query as a parameter. Here is an example of the script:
<?php
$con = mysql_connect(host,username,password);
mysql_select_db(game_server);
//My first query
$q1 = mysql_query('SELECT * FROM game_characters ORDER BY score DESC LIMIT 10');
while($character = mysql_fetch_object($q1)){
//My second query
$q2 = mysql_query('SELECT * FROM game_board WHERE id="'.$character->id.'"');
$player = mysql_fetch_object($q2);
}
?>
So if I have a result of 100 rows, then the second query will execute 100 times. And I know it is not good. How can I make it better. Is there a way to do everything in one query? What if there is another query inside the while loop where a data from the second query as a parameter is used?
P.S.: I am doing a rankings system for an online game.
You can do it in one query if you use JOINs.
SELECT * FROM game_board AS b
LEFT JOIN game_characters AS c ON b.id = c.id
ORDER BY c.score DESC
LIMIT 10
You can also use nested query
SELECT * FROM game_board AS b WHERE
id IN (SELECT id FROM game_characters AS c ORDER BY score DESC LIMIT 10)
You can also put all game_character.id into an array, and use
$sql = "SELECT * FROM game_board AS b WHERE b.id IN (" . implode(', ', $game_character_ids) . ")";
Why not using JOIN?
This way there will be no queries within the while loop:
$con = mysql_connect(host,username,password);
mysql_select_db(game_server);
//My first query
$q1 = mysql_query('
SELECT *
FROM game_characters gc
LEFT JOIN game_board gb ON gc.id = gb.id
ORDER BY score DESC
LIMIT 10
');
while($character = mysql_fetch_object($q1)){
// do Your stuff here, no other query...
}
A better approach here would be to collect all the IDs in a concatenated string str in form 'id1', 'id2', 'id3', ... and use:
select * from game_board where id in (str)
What about if you do something like the following:
<?php
$con = mysql_connect(host,username,password);
mysql_select_db(game_server);
//My first query
$q1 = mysql_query('SELECT * FROM game_characters ORDER BY score DESC LIMIT 10');
while($character = mysql_fetch_object($q1)){
//My second query
$characters .= " ' $character->id ' ,"
}
$q2 = mysql_query("SELECT * FROM game_board WHERE id in (substr($characters,0,strlen($characters - 2))");
$player = mysql_fetch_object($q2);
?>

total sum of a row

I have this query which gives me the transactions for a user, and the output is a table with the information. There is this row named basket_value which contains some numbers, and I need to get the sum of those numbers. Could you please help me?
$query3 = 'SELECT users.first_name,users.last_name,users.phone,
retailer.date, SUM(retailer.basket_value),
retailer.time,retailer.location,retailer.type_of_payment
FROM users ,retailer
WHERE users.user_id="'.$id_user.'"
AND users.user_id=retailer.user_id GROUP BY users.user_id';
$result3 = mysql_query($query) or die(mysql_error());
// Print out result
while($row = mysql_fetch_array($result3)) {
echo "Total ". $row['user_id']. " = $". $row['SUM(basket_value)'];
echo "<br />";
}
I suppose that also your query have some problem and suppose that you have an id to retrieve users, I would do in that way
$query3 = 'SELECT users.user_id,users.first_name,users.last_name,
users.phone, retailer.date,
SUM(retailer.basket_value) as total_sum,
retailer.time,retailer.location,retailer.type_of_payment
FROM users ,retailer WHERE users.user_id="'.$id_user.'"
AND users.user_id=retailer.user_id
GROUP BY users.user_id,users.first_name,users.last_name,
users.phone, retailer.date,retailer.time,retailer.location,
retailer.type_of_payment '
$result = $mysqli->query($query3);
Now if you want the sum for each user:
while ($row = $result->fetch_row()) {
echo "Player: ".$row['user_id']." total: ".$row['total_sum'];
}
If you want the WHOLE GLOBAL sum, you have to way:
Modify your query in that way:
SELECT SUM(retailer.basket_value) as total_sum
FROM retailer
Sum into while loop like: $total += $row['total_sum'];
You're missing a GROUP BY on your query. You most likely want to add GROUP BY users.user_id
Try this query:
SELECT u.first_name, u.last_name, u.phone, SUM(r.basket_value) as total_sum
FROM users u
JOIN retailers r
ON u.user_id = r.user_id
WHERE u.user_id="'.$id_user.'"
GROUP BY u.user_id
You can omit all other columns in the select list and only have the sum() aggregate run on the set to avoid the GROUP BY clause.
$query3 = 'SELECT SUM(retailer.basket_value) as total_sum
FROM users ,retailer WHERE users.user_id="'.$id_user.'"
AND users.user_id=retailer.user_id';

Categories