I have table of likes/dislikes on game: id, game_id, type(like/dislike), time
Table example: Image Link
This code gives me the last week games the had likes, order by their likes count:
$limit = 10;
$time = _time() - 60*60*24*7;
$games_id = array();
$games_id_query = $this->db->execQuery("SELECT `game_id`, count(*) as `likes_count` FROM `likes` WHERE `type` = 'like' AND `time` > '{$time}' group by `game_id` order by `likes_count` DESC LIMIT {$limit}");
$games_id_num = $games_id_query->num_rows;
if($games_id_num > 0) {
while($row = $games_id_query->fetch_object()) {
unset($row->likes_count);
$games_id[] = (array) $row;
}
}
I need addition to this code. I want one more order by, and it will be the dislikes count of this game_id, ASC.
How should I do this? with SQL only... thanks very much!
You probably want something like this:
SELECT `game_id`,
SUM(IF(`type` = 'like', 1, 0)) AS likes_count,
SUM(IF(`type` = 'dislike', 1, 0)) AS dislikes_count
FROM `likes`
WHERE `time` > '{$time}'
GROUP BY `game_id`
ORDER BY `likes_count` DESC, `dislikes_count` ASC
LIMIT {$limit}
That being said, please look into using prepared statements and parameterized queries instead of directly embedding your PHP variables in your SQL.
See this question for more information: How can I prevent SQL injection in PHP?
Change from DESC to ASC, is that what you want?
SELECT game_id, count(*) as likes_count
FROM likes
WHERE type = 'like'
AND time > '{$time}'
group by game_id
order by likes_count ASC LIMIT {$limit}
Related
Hi, i want to get data from chat table like this:
6
7
8
My Code show like this:
8
7
6
Code:
"SELECT * FROM `chat` WHERE
`chat-code` = 'vm1mxo3dpi9gzuo' AND (`user_1` = '1' OR `user_2` = '1')
ORDER BY id DESC LIMIT 3"
Because you're ordering your result in descending order. You should remove the desc in ORDER BY. You can explicitly put ASC to indicate the order as ascending.
Try to read what will happens if you use DESC or ASC statements. https://dev.mysql.com/doc/refman/5.7/en/sorting-rows.html
Hope it will help you.
use this mat and you can change the between parameters with prepared statements.comment if doesn't work.
"SELECT * FROM `chat` WHERE `chat-code` = 'vm1mxo3dpi9gzuo'
AND (`user_1`='1' OR `user_2` = '1')
AND `id` between 6 and 10 //starting and ending offset for query so query doesn't take long time
ORDER BY id ASC LIMIT 3" // LIMIT 3 as you mentioned and ASC order
SELECT a.*
FROM
( SELECT *
FROM chat
WHERE `chat-code` = 'vm1mxo3dpi9gzuo'
AND 1 IN(user_1,user_2)
ORDER
BY id DESC
LIMIT 3
) a
ORDER
BY id;
I have the solution of your problem - use below query:
SELECT * FROM (
SELECT * FROM `chat`
WHERE `chat-code` = 'vm1mxo3dpi9gzuo' AND
(`user_1` = '1' OR `user_2` = '1')
ORDER BY `text` DESC LIMIT 3
) t ORDER BY `text` ASC
SELECT * FROM `chat`
WHERE `chat-code` = 'vm1mxo3dpi9gzuo'
AND (`user_1` = '1' OR `user_2` = '1')
ORDER BY id LIMIT 3 OFFSET 5
Try above query.
You can simply change your query to this (order by text ASC):
SELECT * FROM `chat`
WHERE `chat-code` = 'vm1mxo3dpi9gzuo' AND
(`user_1` = '1' OR `user_2` = '1')
ORDER BY text ASC LIMIT 3
If you still want to order by ID, simply change the DESC to ASC
I spent my whole evening researching and trying to figure out what's wrong with my search query. I do some wildcard search using union queries and pagination.
$current_page = 0;
$search1 = $search;
$search2 = $search."%";
$search3 = "%".$search."%";
$pdo = DB::connection()->getPdo();
$stmt = $pdo->prepare('
SELECT id, desc FROM table WHERE desc LIKE :search1 LIMIT :skip, 15
UNION
SELECT id, desc FROM table WHERE desc LIKE :search2 LIMIT :skip, 15
UNION
SELECT id, desc FROM table WHERE desc LIKE :search3 LIMIT :skip, 15
');
$stmt->bindParam(':search1', $search1);
$stmt->bindParam(':search2', $search2);
$stmt->bindParam(':search3', $search3);
$stmt->bindParam(':skip', $current_page, PDO::PARAM_INT);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
The first query (without the unions) works fine, or if I remove the :skip parameter, it works fine as well.
Any ideas what's wrong?
Using named parameters in PDO, you can't use the same name more than once, unless you do:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
But if you do that, the values for :skip will be interpolated into the query as quoted strings, which are not valid in the context of LIMIT. In other words the following:
LIMIT '0', 15
results in syntax error, because LIMIT wants only true integers as its arguments.
For more examples and explanation, see my answer to Parametrized PDO query and LIMIT clause - not working
So your choices are to add a separate parameter for each occurrence of :skip:
$stmt = $pdo->prepare('
SELECT id, desc FROM table WHERE desc LIKE :search1 LIMIT :skip1, 15
UNION
SELECT id, desc FROM table WHERE desc LIKE :search2 LIMIT :skip2, 15
UNION
SELECT id, desc FROM table WHERE desc LIKE :search3 LIMIT :skip3, 15
');
$stmt->bindParam(':search1', $search1);
$stmt->bindParam(':search2', $search2);
$stmt->bindParam(':search3', $search3);
$stmt->bindParam(':skip1', $current_page, PDO::PARAM_INT);
$stmt->bindParam(':skip2', $current_page, PDO::PARAM_INT);
$stmt->bindParam(':skip3', $current_page, PDO::PARAM_INT);
Or else interpolate the value into the query yourself, without quoting the integer.
But I agree with the comment from #Class, you don't have to do UNION at all. If nothing else, '%search%' works for both of the other two patterns: 'search%' and '%search'. You don't have to search all three.
Just as an update, if someone ended up here trying to implement a similar search that returns results by relevancy, the original query above will duplicate some of the results, and the limit for each select will skip some of the results.
After some testing the following query seems to do the job as expected:
$current_page = ($_GET['page'] - 1) * 15;
$search1 = $search;
$search2 = $search."%";
$search3 = "%".$search."%";
$pdo = DB::connection()->getPdo();
$stmt = $pdo->prepare('
SELECT id, desc FROM table WHERE desc LIKE :search1
UNION
SELECT id, desc FROM table WHERE desc LIKE :search2 AND desc NOT LIKE :search1a
UNION
SELECT id, desc FROM table WHERE desc LIKE :search3 AND desc NOT LIKE :search2a
LIMIT :skip, 15
');
$stmt->bindParam(':search1', $search1);
$stmt->bindParam(':search1a', $search1);
$stmt->bindParam(':search2', $search2);
$stmt->bindParam(':search2a', $search2);
$stmt->bindParam(':search3', $search3);
$stmt->bindParam(':skip', $current_page, PDO::PARAM_INT);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
Put each SELECT in parentheses.
from documentation
To apply ORDER BY or LIMIT to an individual SELECT, place the clause inside the parentheses that enclose the SELECT:
$stmt = $pdo->prepare('
(SELECT id, desc FROM table WHERE desc LIKE :search1 LIMIT :skip, 15)
UNION
(SELECT id, desc FROM table WHERE desc LIKE :search2 LIMIT :skip, 15)
UNION
(SELECT id, desc FROM table WHERE desc LIKE :search3 LIMIT :skip, 15)
');
I tried something like this:
$changed = mysql_query("SELECT * FROM games WHERE changed = 'y' AND human = '$_GET[human]' ORDER BY id DESC LIMIT 100", $link);
$num_rowsc = mysql_num_rows($changed);
So what i want is to select last 100 where human = yes and count where changed = y ..
so get last 100 humans and count how many of them have on changed yes
Are you looking for something like this :
$stmt = $pdo->prepare("SELECT COUNT(*) AS cnt FROM ( SELECT * FROM games
WHERE human= :human ORDER BY id DESC LIMIT 100
) WHERE changed = 'y' ");
$stmt->bindParam(':human', $_GET[human]);
$stmt->execute();
Maybe with this query?
SELECT COUNT(*) AS cnt FROM (
SELECT * FROM games
WHERE human = '".mysql_real_escape_string($_GET[human])."'
ORDER BY id DESC LIMIT 100
) tmp WHERE changed = 'y'
1) try using this as your query:
SELECT count(*) FROM (SELECT * FROM games WHERE changed = 'y' ORDER BY id DESC LIMIT 100) WHERE human = '$_GET[human]'
2) use mysqli
select count(*) as cnt from (
SELECT human FROM games WHERE human = '$_GET[human]' ORDER BY id DESC LIMIT 100
) as changes WHERE changed = 'y'
I have 3 tables: questions, articles and pictures
The rows in each table contain a current_timestamp column posted, and link to an id. I'd like to sort the results of the rows of all three by their timestamp and only echo the newest of the three (for example: if the question is newest from the ID, display that only)
if(count($interests) != 0){ foreach($interests as $interests_following){
$interestid = mysql_result(mysql_query("SELECT `id` FROM `interests` WHERE `name` = '$interests_following'"),0);
$interestquestions = #mysql_result(mysql_query("SELECT `question_text`, `posted` FROM `questions` WHERE `interest` = '$interests_following'"),0);
$interestarticles = #mysql_result(mysql_query("SELECT `article_title`, `posted` FROM `articles` WHERE `interest_id` = '$interestid'"),0);
$interestpictures = #mysql_result(mysql_query("SELECT `interest_pic_title`, `posted` FROM `interest_pictures` WHERE `interest_id` = '$interestid'"),0);
echo '.$interests_following.': //<Only display 1 newest item (article/picture/question here>
Use UNION ALL:
SELECT posted
FROM
(
SELECT `question_text`, `posted` FROM `questions`
WHERE `interest` = '$interests_following'
UNION ALL
SELECT `article_title`, `posted` FROM `articles`
WHERE `interest_id` = '$interestid'
UNION ALL
SELECT `interest_pic_title`, `posted` FROM `interest_pictures`
WHERE `interest_id` = '$interestid'
) t
ORDER BY posted DESC LIMIT 1
To get a single row back:
$sql = "SELECT * FROM WHERE `name`='$interests_following' ORDER BY `posted` DESC LIMIT 1";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
All of the work is in the SQL
ORDER BY `posted` DESC LIMIT 1
This orders results to have the newest first, then only return the first row.
If you mean to return only one item out of the 3 tables, you have 2 choices:
Fetch a row from each and then determine the newest in PHP
Use a UNION to find the single newest row in SQL
The latter makes for less code, but will probably be less readable.
try this
$interestquestions = #mysql_result(mysql_query("SELECT `question_text`, `posted` FROM `questions` WHERE `interest` = '$interests_following' ORDER BY timestamp_field DESC limit 1"),0);
this will show only the latest data base on your timestamp.
I'll show you the SQL queries so you can see what I did; adapt it to your code as needed.
SELECT
(SELECT question_text
FROM questions ORDER BY posted DESC LIMIT 1 ),
(SELECT article_title
FROM articles ORDER BY posted DESC LIMIT 1 ),
(SELECT interest_pic_title
FROM interest_pictures ORDER BY posted DESC LIMIT 1)
;
This sorts by the timestamp DESCending, so the latest record is first, then limits it to the single record. The result will be question_text, article_title, interest_pic_title.
I would like to limit the query below to 5 results. But not just any 5 results. The 5 lowest values for points. How can I do this?
$side = "SELECT title, points, submissionid
FROM submission
WHERE points >= '$sidepoints'
ORDER BY points DESC";
EDIT: I want the results ordered by points descending.
In MySQL:
$side = "SELECT title, points, submissionid
FROM submission
WHERE points >= '$sidepoints'
ORDER BY points ASC
LIMIT 5";
EDIT
You can use the above query with the following PHP code or use a different SQL Query.
PHP Reverse results (untested)
$q = mysql_query($side);
$results = array();
while($r = mysql_fetch_assoc($q))
{
$results[] = $r;
}
$results = array_reverse($results);
foreach($results as $result)
{
echo $result['points']; // etc
}
Or the SQL way (untested as well - found from this post)
SELECT title, points, submissionid
FROM (
SELECT title, points, submissionid
FROM submission
WHERE points >= '$sidepoints'
ORDER BY points ASC
LIMIT 5
) AS t1 ORDER BY points DESC
Try to order your query result with another query (subquery)
SELECT * FROM (
SELECT title, points, submissionid
FROM submission
WHERE points >= '$sidepoints'
ORDER BY points ASC
LIMIT 5
) t ORDER BY t.points DESC
if you are using MYSQL use LIMIT.
$side = "SELECT title, points, submissionid
FROM submission
WHERE points >= '$sidepoints'
ORDER BY points DESC
LIMIT 5";
The ansi sql uses TOP. This will work for sql server
$side = "SELECT TOP 5 title, points, submissionid
FROM submission
WHERE points >= '$sidepoints'
ORDER BY points DESC";
SELECT ... ORDER BY points ASC LIMIT 5 ?