Mysql Query wont echo all results! PHP - php

My code goes like this,
$sql = "SELECT Month(time) as Month, Year(time) as Year,
title, COUNT(*) AS total FROM posts GROUP BY Year, Month ORDER BY time DESC";
$stmt = $conn->query($sql);
if ($stmt->num_rows > 0) {
while($row = $stmt->fetch_array()){
echo "<div class=title>" . $row["title"]. "</div>";
}
}
it is supposed to output 4 titles,
Bellavisa
Mist Neting
Turkey is cool!
Cock of the Rock
but it only outputs
Bellavisa
Turkey is cool!
Cock of the Rock
Note that bellavisa and mist neting are in the same year and month, (setting up an archive list)
EDIT
Here is some of the table data
title "bellavisa" content "yadadada" time "timestamp ..." Author "author"
title "mist nesting" content "yadadada" time "timestamp ..." Author "author"

Well, title is per post, so to get all the titles you should use no GROUP BY, while COUNT(*) is per month, so to get counts you need to GROUP BY the way you do, so in a simple SELECT you can either select one or another, but not both.
To select both, you need to use a subquery, something along the lines of
$sql = "SELECT Month(time) as Month, Year(time) as Year, title, (SELECT COUNT(*) FROM posts WHERE Month(time) = Month AND Year(time) = Year) AS total FROM posts ORDER BY time DESC;";
Effectively, the query selects all the posts, and for each post computes a count. It is not the most efficient way to do that, you can rewrite it using a join, if every post has a unique ID. But for a table with reasonable size this query will work just fine.

Related

Best average rating

I have created a simple rating system for news articles. The news articles are stored in the database table called 'articles'. Each article has a unique id, starting from 1.
So I have 2 articles, ID 1 and ID 2.
I also have a table called 'ratings' that takes the users unique ID, the article ID and the rating that the user gave.
If I give an article with ID 2 a 5/5 star rating, it goes into the 'ratings' table, with article ID 2, my user ID and the rating of 5.
I have figured out how to display the average rating of each article, but I would like to find out how to show the BEST average rating of articles in descending order. Is that at all possible? How could this be done?
Here is how I find the average:
<?
$votesForThis = 0;
$sql = "SELECT * FROM ratings WHERE articleID = ".$articleID." ORDER BY id ASC";
// Check if there are results
if ($result = mysqli_query($con, $sql)) {
// Loop through each row in the result set
while($row = mysqli_fetch_assoc($result)) {
$votesForThis++;
}
}
$result = mysqli_query($con, 'SELECT SUM(vote) AS vote_sum FROM ratings WHERE articleID=' . $articleID);
$row = mysqli_fetch_assoc($result);
$voteSum = $row['vote_sum'];
$averageVotes = $voteSum / $votesForThis;
?>
MySQL has an avg function you can use instead of implementing this logic yourself. From there, it's just a matter of grouping by the article ID and ordering by the average:
SELECT articleID, AVG(vote)
FROM ratings
GROUP BY articleID
ORDER BY 2 DESC
The best practice for doing this is to add a new column to your article table called average_rating and update it with a cron job or after every voting.
Keep in mind that after a while your rating table will become giant and calculating average rating on every page refresh will put huge load on your server.
I would use de-normalization in this one.
I would use triggers to update a previously created column on table articles which would store it's average rating.
I would have posted an example of trigger but you haven't posted which database are you using.
Mysql: https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html
Postgresql: https://www.postgresql.org/docs/9.1/sql-createtrigger.html
Each time a rating it's done, updated or deleted a trigger would update this column with it's current average using the built-in avg function.
At the end you'll only have to create a select on the articles table ordered by this rating column desc.
And create an index on this average rating column to have even faster results.
SELECT articleID, AVG(vote)
FROM ratings
GROUP BY articleID,vote
ORDER BY DESC
used this Query

count(*) in each of previous 25 months separately

I have a database name "d" and there is table name "t"...
t has two columns id and month...
I have to calculate no of ids in each month.
actually, I am taking an input in $monthyear, now I want to store count(id) of previous 25 month in a $row
I use this type of commands
$search = "SELECT * FROM `d`.`t` where id>2";
$result = mysqli_query($con, $search);
$row = mysqli_fetch_array($result);
please tell me a query which can do this trick and can you store it like
$row[0]="no of ids in the inputed month"
$row[1]="no of ids in the [inputed month - 1 month]"
$row[2]="no of ids in the [inputed month - 2 month]"
and so on....
note: both month and "years" do matter.
If not all month has IDs , then you need to use a derived table. Something like this:
SELECT t.monthyear, COALESCE(COUNT(s.monthyear),0) as numOfID
FROM(SELECT '012016' as monthyear
UNION ALL
SELECT '022016'
....) t
LEFT JOIN YourTable s
ON(t.monthyear = s.monthyear)
GROUP BY t.monthyear

in SQL/PHP returning id with the highest and 2nd-5th highest date

As said in the title, I need FIVE queries that returns the ID for rows with the 1st-5th most recent date.
Table: film
id releasedate
232143 2013-06-20
536523 2013-07-20
453554 2013-08-20
098776 2013-09-20
549302 2013-10-20
i.e the first query would return the id 549302
I think this would work for the first query:
$first = $db->query("SELECT id, FROM film WHERE MAX(releasedate)" );
PS: Sorry for the poor formatting of this post, can anyone tell me how to display tables appropriately?
I need to display each id at different points on the web page. Simply returning a list of ids won't suffice. What I really need is for each id to be encapsulated into a unique variable so i can call them at different points on the web page.
No, you don't need five queries.
$first = $db->query("SELECT `id` FROM `film` ORDER BY `releasedate` DESC LIMIT 5" );
This will get the IDs from the database of the five most recent films in your table.
To access each of these just run through a while loop.
while($row = $first->fetch_assoc()) {
$row['id']; # Each ID will be available like this.
}
If you really need to do this in separate queries, you can use the 2-argument form of the LIMIT clause, which is LIMIT offset, count. To get the newest film, use
SELECT id FROM film ORDER BY releasedate DESC LIMIT 0, 1
To get the 2nd most recent film, use
SELECT id FROM film ORDER BY releasedate DESC LIMIT 1, 1
the next one is
SELECT id FROM film ORDER BY releasedate DESC LIMIT 2, 1
and so on.
But it should be better to get them all in one query with
SELECT id FROM film ORDER BY releasedate DESC LIMIT 5
You can then save them all in an array with:
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$ids[] = $row['id'];
}
Then you can use $ids[0] to display the most recent film, $ids[1] for the second most recent, and so on.

mysql collection of visitor days?

I have a mysql table - table1. It has ID (autoinc), dt (datetime), name (varchar) columns. When a visitor visits they can enter their name in the database. On some days their are no visitors.
From this, i'm trying to find if their is some way to make a list in php of all days for which their was at least 1 visitor.
Any ideas?
Select distinct date(dt) from table1
So then, in php you would do something like:
$result = mysql_query("select distinct date(dt) from table1");
while($row = mysql_fetch_array($result)){
echo $row[0] . "\n";
}
This would print each date on a different line.
Should give you a list of the unique dates that data was written to the table.
Updated to use date() instead of day()
*Updated to fix the missing parenthesis *
To extract only those dates.
SELECT DATE_FORMAT(dt, '%Y-%m-%d') AS the_date,
COUNT(*) AS visitors
FROM table
GROUP BY the_date
HAVING visitors > 0;

mysql select statement and limiting the number of records

I am coding a blog post kind of thing, where the author will post the article and it will be displayed in the front end, my problem starts for selecting the posts as i have to meet certain conditions for posting the news in the front end,
I have 4 fields in the database namely
title
pic_title
pic_brief
pic_detail
you guessed it right apart from the title table the rest of three will hold the path to the images in varchar datatype, which will be used to display as the post, the format of the front end is such that
a) there will be total of eight post
displaying in the front end (eight
entries from the database)
b) there will be three post on the top which will include the value from
the table title, pic_title and
pic_brief (total of 3 values)
c) and the rest five will contain just the title and pic_title
(excluding the three entries of top)
Please NOTE: i want the second query to exclude the top 3 record
which already exist in the top i.e
(first query = 3 post in descending
order, second query = 8 - first 3 = 5
post)
The Order of the Post i want is by id DESC
EDIT: I took the first query as
SELECT * FROM news ORDER BY id DESC LIMIT 3
Now if i take the same second query and try populating the values by desc order again the same records will be accessed
In simple words i want a query that will skip the last three records order by id DESC
How do i achieve this feat in PHP?
If you just want the SQL, here it is:
First query
SELECT * FROM `table` LIMIT 3
Second query
SELECT * FROM `table` LIMIT 3,5
(where table is the name of your table of course. Of course you may want to add some ORDER BY clause. To execute these queries in PHP, I suggest reading the manual. If you have any specific problems after doing so, then you can post a new question.
This is a situation where I'd likely opt to select all eight records at once - the less trips to the database, the better.
SELECT t.title,
t.pic_title,
t.pic_brief
FROM TABLE t
ORDER BY t.id DESC
LIMIT 8
...because the rest is just presentation:
$query = sprintf("SELECT t.title,
t.pic_title,
t.pic_brief
FROM TABLE t
ORDER BY t.id DESC
LIMIT 8");
// Perform Query
$result = mysql_query($query) or die( mysql_error() );
$rowcount = 1;
// Use result
while ($row = mysql_fetch_assoc($result)) {
if(rowcount <= 3) {
echo $row['title']
echo $row['pic_title']
echo $row['pic_brief']
} else {
echo $row['title']
echo $row['pic_title']
}
++$rowcount;
}
first query will be like this
"select title, pic_title , pic_brief from table_name order by post_id desc limit 0 , 3"
and rest of five will be
"select title, pic_title from table_name order by post_id desc limit 3 , 5"
second query will exclude the three results returned by first query...
If you want more perfection you can collect all three Ids returned by first query and can add NOT IN in second query.
"select title, pic_title from table_name where post_id not in (1,2,3) order by post_id desc limit 0 , 5";

Categories