Mysql build query with multiple constraints - php

I am trying to set up a query that outputs the 5 most read articles over the last 4hrs. However, if there are no new articles over the last 4hrs, the list will be empty. What I would like is a query that outputs 5 articles over the last 4hrs. If there are no 5 articles in the last 4hrs, but lets say only 2, I would like to add 3 more newest articles to the list (sorted by log_time).
So the query should always output 5 articles.
I am wondering if this can be done in one query.
$sqlCommand = "SELECT * FROM feeds where category like '$category' AND log_time > NOW() - INTERVAL 4 HOUR ORDER BY feed_hits DESC LIMIT 5";
$query = mysqli_query($myConnection, $sqlCommand) or die (mysqli_error());
While ($row = mysqli_fetch_array($query)) {
$fid1 = $row["id"];
$feed_id1 = $row["feed_id"];
$link1 = $row["link"];
$title1 = $row["title"];
$output .= '' . $title1 . '<br/>';
}
mysqli_free_result($query);
echo $output;

You can achieve this via a UNION query. The first half of the below query is simply your original query, which may return up to 5 matching records. The second half of the query returns an arbitrary number of records which are older than 4 hours. The entire query is then ordered by log time, with a limit of 5. This puts your recent target records first, with the older records taking any available positions should they be needed.
SELECT *
FROM
(SELECT * FROM feeds
WHERE category like '$category' AND log_time > NOW() - INTERVAL 4 HOUR
ORDER BY feed_hits DESC LIMIT 5) t1
UNION ALL
(SELECT * FROM feeds
WHERE category like '$category' AND log_time <= NOW() - INTERVAL 4 HOUR) t2
ORDER BY log_time DESC
LIMIT 5;

You could not limit for 4 HOUR and order by log_time limit 5
"SELECT *
FROM feeds
where category like '$category'
ORDER BY log_time DESC LIMIT 5";
and if you need ordered by feed_hits you can reorder the result set
"select * from ( SELECT *
FROM feeds
where category like '$category'
ORDER BY log_time DESC LIMIT 5 ) t order by feed_hits ";

Simply remove the time filtering and instead order by time, this will always give you the latest:
SELECT * FROM feeds WHERE category LIKE '$category' ORDER BY log_time DESC, feed_hits DESC LIMIT 5

Related

How to get last row a value without using loops for MySql query in limited more than 1

I want to known how to get last row a value without using while loop for mysql query.
Select data:
$sql = "
SELECT *
FROM status
WHERE author = '$pname'
AND postdate >= '$lsposttime'
ORDER
BY postdate ASC
LIMIT 4";
$query = mysqli_query($conn, $sql);
I want to get 4th row postdate value withoutusing loops.
Not using this:
while ($row = mysqli_fetch_assoc($query)){
}
select *
from status
where author = '$pname'
and postdate >= '$lsposttime'
order by postdate asc LIMIT 3, 1
this will get the fourth row
You can use a query like this:
SELECT *
FROM (
SELECT *
FROM STATUS
WHERE author='$pname'
AND postdate >= '$lsposttime'
ORDER BY postdate ASC LIMIT 4
) tnp
ORDER BY postdate DESC LIMIT 1;
This will return the last row. So if the result only return 2 row it will give the second.
You can use offset in mysql for fetch data from exact place an order.
For your Requirement your query will looks like:
$sql = "
SELECT *
FROM status
WHERE author = '$pname'
AND postdate >= '$lsposttime'
ORDER
BY postdate ASC
LIMIT 1 OFFSET 4";
$query = mysqli_query($conn, $sql);
And for more use of offset you can discover from here

Select only 5 random rows in the last 50 entries

I'm just starting with MySQL so I would like to know how can I select only 5 random rows in the last 50 entries of my database? I hope you understand my question.
I'm using PDO and what I have now is this:
$otherChoiseRig = $bdd->query("SELECT * FROM articulos WHERE cat = '$ArtCat' ORDER BY RAND() ");
$otherChoiseRig2 = $otherChoiseRig->fetchAll(PDO::FETCH_ASSOC);
Then I use a PHP foreach loop...
Thank you
The challenge is determining the last 50 entries. Assuming you have an auto-incremented id, you can do:
SELECT a.*
FROM (SELECT a.*
FROM articulos a
WHERE cat = '$ArtCat'
ORDER BY id DESC
LIMIT 50
) a
ORDER BY RAND()
LIMIT 5;
The key idea is the subquery to get the last 50 entries, and then the final query to get the 5 random rows. The subquery needs to specify how you identify the last 50.
$otherChoiseRig = $bdd->query("SELECT * FROM articulos WHERE cat = '$ArtCat' ORDER BY RAND() LIMIT 5 ");
$otherChoiseRig2 = $otherChoiseRig->fetchAll(PDO::FETCH_ASSOC);
just add limit
i assume in your table you have some date column so we can get last 50
SELECT * FROM (SELECT * FROM articulos WHERE cat = '$ArtCat' ORDER BY created_tiem desc limit 50 ) t order by RAND() limit 5;

Display 5 most recent forum posts

So I have 3 tables inside of my database, let's say 1_comments, 2_comments and 3_comments and I want to display the latest 5 posts of all 3 tables at once in PHP and sort by the most recent time. My code is:
<?php
$row="";
$link = mysql_connect("localhost","username","password");
mysql_select_db("database");
$query = "SELECT * from 1_comments ORDER by timestamp DESC limit 5";
$result = mysql_query($query);
while($row = mysql_fetch_array($result)) {
echo "<ul>";
echo "<li>".$row['comment']."</li>";
echo "</ul>";
}
mysql_close($link);
?>
So it's taking the most recent 5 posts from the comments row on 1_comments and sorting them by their most recent timestamp, but I can't seem to get it working for 1_comments, 2_comments and 3_comments all at once.
If all tables have the same structure you can use UNION.
Something like:
(SELECT * from 1_comments ORDER by timestamp DESC limit 5)
UNION
(SELECT * from 2_comments ORDER by timestamp DESC limit 5)
UNION
(SELECT * from 3_comments ORDER by timestamp DESC limit 5)
ORDER BY timestamp DESC limit 5
However, I would take a good look at the database structure and try to reduce the 3 similar tables to just one.

MYSQL Select from table, get newest/last 10 rows in table

What's the best, and easiest way to do this? My query currently is:
SELECT *
FROM chat
WHERE (userID = $session AND toID = $friendID)
OR (userID = $friendID AND toID = $session)
ORDER BY id
LIMIT 10
This shows the first 10 rows though, not the last 10.
EDIT: I Want the last 10 rows (Which yes, DESC does this) However I want them to be returned in ASCENDING order.
to reverse the order (therefore get last 10 instead of first 10), use DESC instead of ASC
EDIT
Based on your comment:
SELECT * FROM (
SELECT *
FROM chat
WHERE (userID = $session AND toID = $friendID)
OR (userID = $friendID AND toID = $session)
ORDER BY id DESC
LIMIT 10
) AS `table` ORDER by id ASC
If you want the last 10 then just change ASC to DESC
SELECT *
FROM
chat
WHERE
(userID=$session AND toID=$friendID)
OR
(userID=$friendID AND toID=$session)
ORDER BY id
DESC
LIMIT 10
$con = mysqli_connect("localhost","my_user","my_password","my_db");
$limit = 10;
$query = "SELECT * FROM $table";
$resource = mysqli_query($con,$query);
$total_rows = mysqli_num_rows($resource);
$start = $total_rows-$limit;
$query_limit= $query." LIMIT $start,$limit";
First I have set the limit
$limit = 10;
then
$total_rows = mysqli_num_rows($resource);
Here I have taken total number of rows affected.
$start = $total_rows-$limit;
then substracted limit from number of rows to take starting record number
$query_limit= $query." LIMIT $start,$limit";
and then added limit to the query.
For more information about limit see this link
https://www.w3schools.com/php/php_mysql_select_limit.asp
First select the last 10 from the table, then re-order them in ascending order.
SELECT * FROM (SELECT * FROM table ORDER BY id DESC LIMIT 10) sub ORDER BY id ASC

Select max 5 integers from set of 20

I'm trying to select the 5 most viewed articles out of a list of the 20 most recent entries in a table. My table structure is essentially this:
id | date | title | content | views
My first thought was just to use an inner select to get the 20 most recent articles, then select from that, but I have yet to have any luck.
//doesn't work (my version of mysql doesn't support LIMIT in sub queries)
$recent = "(SELECT id FROM news ORDER BY date DESC LIMIT 20)";
$result = $db->query("SELECT id, title, date, content FROM news WHERE id IN $recent ORDER BY views DESC LIMIT ".self::RECENT_MAX);
//neither does this (syntax error # 'OFFSET 20')
$recent = "(SELECT MAX(date) FROM news ORDER BY date DESC OFFSET 20)";
$result = $db->query("SELECT id, title, date, content FROM news WHERE date > $recent ORDER BY views DESC LIMIT ".self::RECENT_MAX);
Anyone got any suggestions on how you would structure this query?
I just tested this and it works
SELECT *
FROM (
SELECT *
FROM news
ORDER BY id DESC
LIMIT 0, 20
) lasttwenty
ORDER BY views DESC
LIMIT 0, 5
Server version: 5.0.51a-3ubuntu5.4
If you're having a lot of issues getting it to work through SQL, I'd suggest just grabbing the 20 most recent articles from the database, then process it in PHP to find the 5 most-viewed. You could either loop over the rows, or just load it all into an array and sort it.
Since I can't think of any way to do that in a single query, I suggest either selecting the top 5 in code, or doing it using two queries, something like:
$items = $db->query("SELECT id FROM news ORDER BY date DESC LIMIT 20");
$recent = array();
foreach ($items->fetchAll() as $item) { $recent[] = $item['id']; }
$recent = "('".join("','", $recent)."')";
$result = $db->query("SELECT id, title, date, content FROM news WHERE id IN {$recent} ORDER BY views DESC LIMIT ".self::RECENT_MAX);
Why don't you run the first (inner) query separately, and create the second query programmatically?
$ids = array();
$result = $db->query("SELECT id FROM news ORDER BY date DESC LIMIT 20");
while ($row = $result->fetch()) {
$ids[] = $row[0];
}
$ids = implode(',', $ids);
$result = $db->query("SELECT id, title, date, content FROM news WHERE id IN ($ids) ORDER BY views DESC LIMIT ".self::RECENT_MAX);
Or something of this nature...
Update: Or you could just simply fetch the first 20 sorted by date, then sort thr result array by views in PHP, and finally take the 5 topmost items (I guess this is what SilentGhost meant in the comment).
Try this...
select top 5 number from
(
select
top 20 (ID) as number
from
news order by date desc
)
as number
EDIT FOR MS SQL
Use the LIMIT for MYSQL

Categories