PHP/MySQL pattern to order posts? - php

I have single table where i put all the content. Each row is one post. I want to be able to manipulate order of posts so that i can push some of those to the top or bottom...
Also, each post belongs to certain category. (i believe that that additional parameter makes difference when ordering posts within certain category)
Please, give me some hints/code patterns how would you do it?
p.s. i don't want to add new tables, make more relations, i want it as simple as possible...

I would personally accomplish this by adding a sort_index field to the table with a default value of something like 100. You can then push posts down by decreasing their sort order, or push them to the top by increasing it. By starting with a specific number, you are establishing a baseline for default sorting of posts.
SELECT * FROM `posts` ORDER BY sort_index DESC, date_posted DESC
This would use ensure posts with the same sort index get a secondary sorting based on the date they were posted.
It also allows you to then easily automate making the posts fall down in the rankings over time with a small script setup as a cron to decrease the sort index of posts every so often until they hit the default value.

Let's say you have a table with the following columns:
id
post
category
You can add a new integer column called rank. Using the new rank column you can order your posts like this:
SELECT `post` from tblPosts order by category, rank;
Now you can order your posts by assigning a rank to them. In the above example smaller numbers will be listed at the top and larger ones at the bottom.

Related

Sort a list with a higher value

Good morning, I would like to create a list of content by ordering them from the most visited one.
I have a table called "post", formed by these different fields:
ID
TITLE
VIEWS
I would therefore like the content list to be shown from the post with the largest views.
I did this:
$pdo->query('SELECT * FROM post ORDER BY views DESC');
But unfortunately it does not work properly, and I do not understand why. It sounds casual, sometimes it shows at the top of the post with fewer views than others, let's say everything randomly, otherwise it's correct. Something wrong?
If your views field is a varchar and you want to sort the values as a number so use ABS of MySQL
$pdo->query('SELECT * FROM post ORDER BY ABS(views) DESC');

SQL - Workaround for Removing Last Element and Updating New one

On my First SQL-Based Project.
I want a News pane on my website.
In that news pane. I want to show Latest 10 News of all time which I keep updating after every new change in website like a changelog.
What will be the workaround for SQL-PHP to Show only the Latest 10 News and How would I update the DataBase Table (Removing the Oldest, 10th Entry) and then Adding Latest(1st Entry) to the table + changing the IDs (1-10).
For this, You can Make a Table(e.g. News). With Column ID content date.
Simply Add the news and the do this.
SELECT * FROM News ORDER BY ID DESC LIMIT 10
then,
Take this into PHP ARRAY and then simply work there.
Rarely would you want to remove the old values from your database straight after adding a new entry, why not just order the database select results and limit the rows, far more flexible for future code changes.
SELECT * FROM News ORDER BY id DESC LIMIT 10;
Assuming that you have timestamp for your news, you might want to order by this database value instead. As this would allow you to 'bump' up news articles later on, for example if you want an edited article to be considered new you would just have to update the timestamp, and not change the row ID to a higher value.
SELECT * FROM News ORDER BY unix_time_stamp DESC LIMIT 10;
Finally if you wanted to clean up your news entries I would do that on a cleanup function separately, probably on some kind of hourly or daily cronjob.

Non standard sorting and navigation using MySQL and PHP

I am trying to sort the information given to me by the API of an engineering journal. I have extracted the following information into a table:
ID (integer),
Journal Entry Name (Text),
Description (Text),
Page Length (integer),
Has Media (boolean)
Each "Journal Entry" has only one ID associated with it. Each ID also has other characteristics that are not returned by the API but that I want to use to sort. They are:
Category (Things like Econ, Math, Biology. Each ID can have more than one category)
Boolean values (Things like requiring special subscriptions)
I have created a second table in the following format:
ID (integer),
Category (text),
Boolean1 (bool),
Boolean2 (bool),
Boolean3 (bool)
Since each ID can have more than one category, when this occurs another row is added to this table. The idea being that any given row only has one ID and one category in it.
What I want to do is this:
Be able to find the top ten categories when it comes to
Highest Journal Entry (ID) count
Highest Total Page Length
Highest Journal Entry count where the "Has Media" boolean is true
Create a means of navigating like "pagination" where each page shows the nth results of the aforementioned top ten.
So if I chose to Highest Journal Entry count method, the first page would be show IDs, Names, and Descriptions of all the Journal entries in the category with the highest count.
My plan has been to create a new table where the numbers one through ten are in the first column, and then populate the second column with the top ten categories. Then I can use a process similar to pagination in which the nth page only shows the values with the corresponding category from the original value. However I can't seem to be able to make this top ten list/matrix, nor do I know if it there is a better way.
Unfortunately I am not a MySQL or PHP coder by trade, and have only gotten this far by lots and lots of googling. I have been completely unable to find any guides for a navigation method like the one I want. And since I don't know the proper terminology, I am just trying random google searches at this point.
Is this the best way to go about it? Or would it be better to create a third table of some sort? Is there perhaps an easier way to do this with something that can use the PHP and MySQL code I already wrote?
Not sure I really understand what you're going for here, but my best guess is that you probably want to combine your two initial tables and have category be a set rather than an individual term so you can have a single entry per unique ID.
Then you'd just need to write calls for each of your top ten finds as needed. Since each id can have an unknown number of categories I would start with a limit of 10 and then process the returns starting with the top match, grab its categories, if there are more than 10 grab the first 10, if there are less than 10 grab what there are, update the amount you're looking for (if there were 4 then you're now looking for 6), and move on to the next best match.
Maybe something like this:
categories = null;
$delimeter = ',';
$count = 1;
$top10 = array();
$result = mysql_query("
SELECT *
FROM table_name
ORDER BY page_length DESC
LIMIT 10");
while($row = mysql_fetch_array($result) && $count <=10)
{
$categories = $row['categories'];
$id = $row['id'];
$splitcontents = explode($delimeter, $catagories);
foreach($splitcontents as $category){
if (!in_array($catagory,$top10)){
$top10[$count] = array(
'category'=>$category,
'journal_id'=>$id
);
$count++;
}
}
}

How to create a 'rising' or 'What's hot' query in Mysql and PHP?

I'm trying to create a filter to show certain records that are considered 'trending'. So the idea is to select records that are voted heavily upon but not list them in descending order from most voted to least voted. This is so a user can browse and have a chance to see all links, not just the ones that are at the top. What do you recommend would be the best way to do this? I'm lost as to how I would create a random assortment of trending links, but not have them repeat as a user goes from page to page. Any suggestions? Let me know if any of this is unclear, thanks!
This response assumes you are tracking up votes in a child table on a per row basis for each vote, rather than just +1'ing a counter on the specific item.
Determine the time frame you care about the trending topics. Maybe 1 hour would be good?
Then run a query to determine which item has the highest number of votes in the last hour. Order by this count and you will have a continually updating most upvoted list of items.
SELECT items.name, item_votes.item_count FROM items
INNER JOIN
(
SELECT item_id, COUNT(item_id) AS item_count
FROM item_votes
WHERE date >= dateAdd(hh, -1, getDate()) AND
## only count upvotes, not downvotes
item_vote > 0
group by item_id
) AS item_votes ON item_votes.item_id = items.item_id
ORDER BY item_votes.item_count DESC
You're mentioning that you don't want to repeat items over several pages which means that you can't get random ordering per request. You'll instead need to retrieve the items, order them, and persist them in either a server-wide or session-specific cache.
A server-wide cache would need to be updated every once in a while, a time interval you'll need to define. Users switching page when this update occurs will see their items scrambled.
A session-specific cache would maintain the items as long as the user browses your website, which means that the items would be outdated if your users never leave. Once again, you'll need to determine a time interval to enforce updates.
I'm thinking that you need a versioned list. You could do the server-wide cache solution, and give it an version (date, integer, anything). You need pass this version around when browsing the latest trends, and the user will keep viewing the same list. Clicking on the Trends menu link will send them to the browsing pages without version information, which should grab the latest from your cache. You then keep this as long as the user is browsing these pages.
I can't get into sql statements, not because they are hard, but we don't know your database structure. Do you keep track of individual votes in a separate table? Are they just aggregated into a single column?
Maybe create a new column to record how many views it has? Then update it every time someone views it and order by threads with the largest number of views.

Selecting rows from MySQL

I'm trying to create a web index. Every advertiser in my database will be able to appear on a few categories, so I've added a categorys column, and in that column I'll store the categories separated by "," so it will look like:
1,3,5
The problem is that I have no idea how I'm supposed to select all of the advertisers in a certain category, like: mysql_query("SELECT * FROM advertisers WHERE category = ??");
If categories is another database table, you shouldn't use a plain-text field like that. Create a "pivot table" for the purpose, something like advertisers_categories that links the two tables together. With setup, you could do a query like:
SELECT A.* FROM advertisers AS A
JOIN advertisers_categories AS AC ON AC.advertiser_id = A.id
WHERE AC.category_id = 12;
The schema of advertisers_categories would look something like this:
# advertisers_categories
# --> id INT
# --> advertiser_id INT
# --> category_id INT
You should design your database in another way. Take a look at Atomicity.
Short: You should not store your value in the form of 1,3,5.
I won't give you an answer because if you starting you use it this way now, you going to run into much more severe problems later. No offense :)
It's not possible having comma-separated values to do this strictly in an SQL query. You could return every row and have a PHP script which goes through each row, using explode($row,',') and then if(in_array($exploded_row,'CATEGORY')) to check for the existence of the category.
The more common solution is to restructure your database. You're thinking too two-dimensionally. You're looking for the Many to Many Data Model
advertisers
-----------
id
name
etc.
categories
----------
id
name
etc.
ad_cat
------
advertiser_id
category_id
So ad_cat will have at least one (usually more) entry per advertiser and at least one (usually more) entry per category, and every entry in ad_cat will link one advertiser to one category.
The SQL query then involves grabbing every line from ad_cat with the desired category_id(s) and searching for an advertiser whose id is in the resulting query's output.
Your implementation as-is will make it difficult and taxing on your server's resources to do what you want.
I'd recommend creating a table that relates advertisers to categories and then querying on that table given a category id value to obtain the advertisers that are in that category.
That is a very wrong way to define categories, because your array of values cannot be normalized.
Instead, define another table called CATEGORIES, and use a JOIN-table to match CATEGORIES with ADVERTIZERS.
Only then you will be able to properly select it.
Hope this helps!

Categories