MySQL Select list In Array - php

Each Article can have unlimited categories.
Categories are saved in the database like this
example article_category: '1','3','8'
OR
example article_category: '2','3'
So when I search for a listing under, lets say category 3
$category_id = $_REQUEST['category_id']; //3
$SQL = "SELECT * FROM ARTICLES WHERE article_category = '$category_id'";
If it were just one the above would work fine.
I hate to say it but I'm completely lost.. Would I use IN ?

= (equals) check against the complete string. what you want to do could be done using LIKE and the % comodin (it's like * for files in dir or the like)
$SQL = "SELECT * FROM ARTICLES WHERE article_category LIKE \"%'$category_id'%\"";
however, i reccommend that you normalize the database and have categories as a subtable

The way I would implement this is by creating a table for categories, which you probably already have. Something like:
cat_id cat_name
1 animals
2 sports
3 locations
Then create a table to link articles to categories. Something like:
table artcat
article_id cat_id
1 1
1 3
2 1
2 2
2 3
The above table basically replaces the field article_category you have currently. In the above example
article 1 is linked to categories 1 and 3
article 2 is linked to categories 1, 2 and 3
And when you need to get all the articles for a given category, all you would run a query like:
SELECT article_id FROM artcat WHERE cat_id=3
You could even do a join with articles database to output the article titles if you wish.
I hope this helps. Good luck!

You can use FIND_IN_SET here, but it may not be very efficient. I suggest that you change your table structure and follow #jdias' answer.
If your article_category is saved as 1,2,3:
$SQL = "SELECT * FROM ARTICLES WHERE FIND_IN_SET('$category_id', article_category)";
Or if it's saved as '1','2','3':
$SQL = "SELECT * FROM ARTICLES WHERE FIND_IN_SET('\'$category_id\'', article_category)";

Related

Retrieving aggregated results from two queries

I am trying to figure out best way to compare results from 2 queries and display the difference.
Table 1 = User Table
Table 2 = Page Table
Table 3 = Assigned table
Example:
There are users 1 and users 2 in the user table.
User 1 has been assigned to 10 pages, user 2 has been assigned to only 1 page.
This works fine for finding which pages they have assigned, which is only 1 page for this example.
SELECT * FROM assigned_table WHERE user= 2
But I can not figure out how to get results of all the other pages it doesn't have access to.
This does not work because there is user 1 that has access to all 10, so it gets the results of all other users except user2
SELECT * FROM assigned_table WHERE user != 2
So basically I need it to say what pages does user2 have access to, and then which pages does it not have access to and display both results separately
Any assistance would be appreciated.
Sorry if similar topic was posted elsewhere, was unable to find what I was looking for.
You should use a join for this. Here's the documentation on this https://dev.mysql.com/doc/refman/5.0/en/join.html.
Something like
select pt.pagename from `Assigned table` as at
join `Page Table` as pt
on at.pageid = pt.id
where at.user = 2
This would give you a listing of all page titles (pagename) user 2 has assigned to him/her. Your column and table names will need to be updated.
Pull all papers not assigned to specific user.
select pagename
from `Page Table`
where id not in (select pageid from `Assigned table` where at.user = 2)

Complex mysql query - grouping and ordering by date

I have a news list, with three categories. Let's say category1, category2, category3. Each article has a publish date. Now is it possible to get the list as follows:
most recent article in category1
most recent article in category2
most recent article in category3
second most recent article in category1
second most recent article in category2
second most recent article in category3
And if both category1 and category3 have one article left while category2 has run out of articles, the above list will be followed by:
third most recent article in category1
third most recent article in category3
I don't know if this is possible in mysql query. Please help!
If your category Number is limited you can loop it and in every loop, concat the sqls with UNION; the this sql:
"SELECT * FROM news WHERE 1 GROUP BY ".$category." ORDER BY publish_date DESC LIMIT ".$categoryCount." UNION ALL"
Note: Don't forget the substr the last "UNION ALL" string
I see questions like this so often, especially when it comes to web-based app content. I want the most recent X per Whatever. In this case, you want the most recent 3 articles. Instead of trying to structure queries that will be a pain to work with, I would suggest denormalizing the data for the news category table..
Add 3 columns for the most recent 3 articles. Then, add a trigger to the articles table. When an article is added to the table, do an update to the category table with it as the newest position, and shift the other two down so it is always rolling... Not positive on the trigger syntax, but something like the following for the update...
update Category
set ThirdArticleID = SecondArticleID,
SecondArticleID = FirstArticleID,
FirstArticleID = NewArticleIDJustAdded
where CategoryID = NewArticleCategoryID
Then, you can just do left-join per category and always have the "latest 3" something like
select
c.*,
A1.ArticleTitle as FirstArticle,
A2.ArticleTitle as SecondArticle,
A3.ArticleTitle as ThirdArticle
from
Category C
LEFT JOIN Articles A1
on C.FirstArticleID = A1.ArticleID
LEFT JOIN Articles A2
on C.SecondArticleID = A2.ArticleID
LEFT JOIN Articles A3
on C.ThirdArticleID = A3.ArticleID
Then you dont have any min(), max(), group by, order by desc, etc to worry about. You may want to pre-prime these category article entries, but after the entries get new articles, it will be self-synchronizing.

PHP: explode array

i have two table for article and setting. in article table i put id,title,date ..etc and in settings table, i have row with name featuredarticle and put id of article with separate comma for featured articles. now i need to list/print my featured article only. how to ?
TABLE articles:
ID | TITLE | DATE | PUBLISH
1
2
3
4
5
TABLE settings / row featuredarticle:
1,2,5
SELECT a.*
FROM articles a
INNER JOIN settings b
ON FIND_IN_SET(a.ID, b.featuredarticle) <> 0
FIND_IN_SET
If you have time to change the table schema, change it. It is a bad design to have columns vith value separated by a comma.
Get data from DB to array and use:
$newArray = explode(".", $dataDbArray);
You can try this-
SELECT * FROM article
JOIN settings ON FIND_IN_SET( id, featuredarticle)
Please have a look at demo: demo

Linked Tables and SQL SELECT Queries

I have a few linked tables in my custom forum: categories, sub_categories and posts
basically, I have people able to add up to three categories and five sub-categories when they make a new post.
I also enable people to 'listen' to certain categories and sub-categories and have them in an easy to access bar at the side of the page.
My tables are set up thus (only showing relavent fields for ease):
posts:
id INT
category_id VARCHAR(12)
sub_category_id VARCHAR(35)
categories:
id INT
name VARCHAR(20)
sub_categories:
id INT
name VARCHAR(20)
in my posts table, I store the set categories and sub-categories by their ID in the following format:
category_id [2][4][8]
sub_category_id [1][2][3][4][5]
thus enabling me to execute the following query in PHP and get the post based on category and sub-category:
SELECT * FROM posts WHERE category_id LIKE '%[{$id}]%' AND sub_category_id LIKE '%[{$id2}]%'
the problem I have is selecting the sub_categories for the access bar that people 'listen' to...
$sql = "SELECT title, id FROM categories";
$query = mysql_query($sql);
$list = array();
while ($row = mysql_fetch_assoc($query)){
$list[$row['title']] = array();
$sql = "SELECT sub_categories.title FROM sub_categories, posts WHERE (category_id LIKE '%[{$row['id']}]%') AND (????) LIMIT 0,100";
$query = mysql_query($sql);
while($result = mysql_fetch_assoc($query)){
$list[$row['title']][] = $result['title'];
}
}
print_r($list);
Obviously you can see where I am stuck (????), but before I explain what I am trying to do, I'll explain what the output I am looking for is.
when I print the $list array, I want it to print a multi-dimensional array featuring the categories as the first key, with their values being an array of sub-categories that have been tagged in the main category.
The problem I have is that in my sub_category_id field on the post table, remember the values are stored in the format [1][2][3] and I need to check the value against the subcategory field id.
I have tried the following:
"SELECT sub_categories.title FROM sub_categories, posts WHERE (category_id LIKE '%[{$row['id']}]%') AND (sub_category_id LIKE '%[sub_categories.id]%') LIMIT 0,100"
But it didn't work. I don't know whether there is an error in my query or whether it even SHOULD work, but I would be grateful if anyone could tell me how to do it or where I am going wrong in my code!
NB. I am trying to find which sub_categories appear in which categories based on people tagging them in a post together.
You're facing problems because you're not aware about few concepts in database...
In your case, you want to create associations called "many-to-many".
It means that a category can be used in many post and a post can be represented by many category.
To translate that into a "SQL" world, you have to create an intermediate table.
this table will store both identifier of the two tables.
for exemple:
-------------------
| categorisation |
-------------------
| post_id | => is the link to posts
| category_id | => is the link to categories
-------------------
When you create a new post, you create a new object in the table post. But you also create N records in the table categorisation.
When you want to retrieve which categories applied to this post, you can do a query like that:
SELECT post.id, post.name
FROM post
INNER JOIN categorisation on (post.id = categorisation.post_id)
INNER JOIN category ON (categorisation.category_id = category.id)
I think you need to read some articles on the web about database before progressing in you project ;)

Mysql syntax using IN help!

i have a pictures table : pictures(articleid,pictureurl)
And an articles table : articles(id,title,category)
So, briefly, every article has a picture, and i link pictures with article using articleid column. now i want to select 5 pictures of articles in politic category.
i think that can be done using IN but i can't figure out how to do it.
Note: Please only one query, because i can do it by selecting articles firstly then getting the pictures.
Thanks
To get five pictures from articles in a category you could do this:
SELECT pictures.pictureurl
FROM articles, pictures
WHERE articles.id = pictures.articleid AND articles.category = 'politic'
ORDER BY [your sort criteria]
LIMIT 5;
You could consider rephrasing the question a bit.
If you are looking for an IN query instead of a JOIN this is an alternative to Alex's query:
SELECT pictureurl
FROM pictures
WHERE arcticleid IN (SELECT id FROM articles WHERE category='politic')
LIMIT 5
Rewritten for clarification (see comments):
If you like to keep your JOIN criteria separated from your SELECT criteria, you can write something like the below:
SELECT pictureurl
FROM pictures
JOIN articles ON id = articleid
WHERE category LIKE 'politics'
ORDER BY RAND()
LIMIT 5
I find the intent slightly clear when it's written like that, and maybe it's just me, but I have encountered complex queries written in the SELECT * FROM a, b, c form that worked under MySQL 4 which choke MySQL 5, whereas the above format works fine with both.
Also, if you use uniform ID column names for conformity, and to avoid confusing yourself in more complex scenarios, you can use the USING clause instead. So if articles ID column is also named articlesid, the JOIN could be written like so:
SELECT pictureurl
FROM pictures
JOIN articles USING (articleid)
...
You don't really need to use IN for this. IN serves when you nest queries or when you have a known set of values to check against.
To select 5 random images in the politics category:
SELECT pictureurl FROM articles, pictures WHERE pictures.articleid = articles.id AND articles.category = 'politics' ORDER BY RAND() LIMIT 5

Categories