I wanted to know if it is possible to obtain the 10 most viewed articles that week (Between today and 7 days back) using PDO PHP.
The main problem is that on two separate tables. Primary table is the table of articles. And the second table is a table visitors by IP.
Posts (ARTICLE TABLE):
1.ID (text)
2.TITLE (text)
3.TEXT (text)
Visitor (COUNTER TABLE):
1.ID (number)
2.IP (text)
3.DATE (TIMESTAMP)
4.ID_POSTS (text)
The full php code:
$week_start = date('Y-m-d',time()+( 1 - date('w'))*24*3600);
$week_end = date('Y-m-d',time()+( 7 - date('w'))*24*3600);
$query = "SELECT * FROM visitor WHERE DATE BETWEEN '".$week_start."' AND '".$week_end."' LIMIT 0, 10 ";
$result = $db->prepare($query);
$result->execute();
$i=1;
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
$post[$i]=$row[ID];
$i++;
}
for ($i = 1; $i <= 10; $i++) {
$query = "SELECT * FROM POSTS WHERE ID_POST = '".$post[$i]."' LIMIT 0, 10";
$result = $db->prepare($query);
$result->execute();
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
echo<<<PRINT
$row[ID].$row[TITLE]: $row[text]
PRINT;
}
}
The problem I think is that you have to count how many people were at the table wrote the secondary then move the primary table.
Steps:
1. Count how many entered each article each week by the secondary table
2. extract the 10 Most Viewed same week
3. present the 10 most read article in the same week by the main table
Thanks in advance.
For such a query, I would expect a COUNT(), GROUP BY, ORDER BY, and LIMIT 10. Hence:
SELECT id_post, COUNT(*) as cnt
FROM visitor v
WHERE DATE BETWEEN '".$week_start."' AND '".$week_end."'
GROUP BY id_post
ORDER BY cnt DESC
LIMIT 0, 10 ;
Note: The WHERE clause always followed the FROM clause.
Also, you should not be embedding dates in the query string. You should learn to use parameters instead.
select * from (select id, count(1) as cnt
from visitor where date > (NOW()- INTERVAL 7 DAY) group by id) v1, posts p
where v1.id = p.id
order by v1.cnt desc
limit 10
Not tested.
Related
I have 2 MYSQL base queries which dependent on each other, here are my quires
#$query = "SELECT * FROM coins_tokens";
$row = $db->Execute($query);
foreach ($row as $rowItem) {
$name = $rowItem['ct_id'];
#$sql1 = "SELECT * FROM historical_data WHERE `name` = '".$name."' GROUP BY name LIMIT 30";
$row2 = $db->Execute($sql1);
foreach ($row2 as $rowItem2){
$market_cap = $rowItem2['market_cap'];
if($market_cap >= 500000000){
}
}
}
It slow down my whole process and take lot of time to execute, as there are more then 1400 results in coins_tokens, then there are more then 600000 records again 1st table, in both table ct_id and name are conman.
And what I am trying to do is to get the currencies which have more then 500million market_cap in last 7 days. So am fetching the currencies from 1st table and there historical data from 2nd table and checking if market_cap there increased in last 7 days.
Here is the structure and data of historical_data table:
SELECT
c.*,
d.`date`,
d.market_cap
FROM coins_tokens AS c
LEFT JOIN historical_data AS d ON c.ct_id = d.name
WHERE d.market_cap >= '$mketcapgrter'
AND DATE(d.`date`) >= CURRENT_DATE() - INTERVAL 30 DAY
GROUP BY d.name
ORDER BY d.market_cap DESC LIMIT 100
I'm trying to keep the 10 most recent entries in my database and delete the older ones. I tried DELETE FROM people ORDER BY id DESC LIMIT $excess, but it just deleted the top 10 entries.
$query = "SELECT * FROM people";
$result = mysqli_query($conn, $query);
$count = mysqli_num_rows($result);
if ($count > 10) {
$excess = $count - 10;
$query = "DELETE FROM people WHERE id IN(SELECT id FROM people ORDER BY id DESC LIMIT '$excess')";
mysqli_query($conn, $query);
}
You can use this:-
DELETE FROM `people`
WHERE id NOT IN (
SELECT id
FROM (
SELECT id
FROM `people`
ORDER BY id DESC
LIMIT 10
)
);
Also your query is logically incorrect and you are fetching the records in descending order. i.e. Latest to older and you are deleting the most recent records. Use ASC instead.
Something like this? Gets the ten latest ids in the subquery, then deletes all of the other ids.
DELETE FROM people WHERE id NOT IN (SELECT id FROM PEOPLE ORDER BY id DESC LIMIT 10)
Your logic is all over the place, [you should ORDER BY ASC, not DESC] and your query will take ages if there are [for example] 10,000 entries because you'll have an IN clause with 9,990 entries to compare all 10,000 to.
Select the 10 most recent, and delete where NOT in.
DELETE FROM people
WHERE id NOT IN(
SELECT id
FROM people
ORDER BY id DESC
LIMIT 10
)
Maybe find the ID of the 10th element and then delete all rows which are older?
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.
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
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