Group post by name from 2nd table php - php

This is litle complicated query for me, but if anyone have idea please post id...
I want to make something like this
SITE 1
post
post
post
SITE 2
post
post
post
here is my query
$result = mysql_query("SELECT content.* FROM content WHERE content.site IN
(SELECT site_id FROM site_subscription WHERE user_id = ".$_SESSION['userid'].")
ORDER by content.site DESC");
while($row = mysql_fetch_assoc($result)) {
$array[] = $row;
}
AND im display post
if(is_array($array)) {
foreach($array as $row) {
include($basepath.'/template/item.php');
}
}
This is working and post is sorted by site_id, but need to get site_name from other table, table name site and than GROUP post by site_name like above SITE 1, SITE 2, SITE 3
Something like
SELECT * FROM site WHERE id='content.site'

$result = mysql_query("SELECT content.* FROM content
INNER JOIN site ON content.site = site.id
WHERE content.site IN
(SELECT site_id FROM site_subscription WHERE user_id = ".$_SESSION['userid'].")
ORDER by content.site DESC");

Do a JOIN instead of subquery. Try something like this:
SELECT content.*, site_name, FROM content
JOIN site_subscription ON content.site = site_id
WHERE site_subscription.user_id = <USER_ID>
ORDER by content.site DESC
GROUP BY site_name
MysSQL will handle this query but it's not fully correct. You can't actually select content.* as you have to select only aggregated fields while you are grouping rows.

"SELECT * FROM content INNER JOIN site ON content.site = site.id
WHERE site.id IN (
SELECT site_id FROM site_subscription
WHERE user_id = ".$_SESSION['userid'].")
ORDER BY site.name"

Related

SQL in php force WHERE IN to find more than one time the same id

I am trying to to do a cart where the products have customizations... To avoid lot of queries in the data base I have tried to save the results in an array after the query. The query looks like this:
$sql = 'SELECT *
FROM cc_restaurants_menu
WHERE menu_id
IN ("7","50","50")
ORDER BY FIELD (menu_id,"7","50","50")';
$result = $conn->query($sql);
if($result->rowCount() > 0) {
while($row = $result->fetch()) {
$names[] = $row['menu_product'] .'<br>';
}
}
But the problem with this is that the query avoid the repeated ids. (I need repeated ids because the people can add the product more than one time).
Is there anyway to get the repeated ids more than one time?
The only idea I have is do something like (if the ids are in an array) :
foreach($ids as $d) {
//query here the database based in each id
}
thanks in advance
Think you might need one query for each menu_id, and use UNION ALL to join the results together.
Something like this:-
SELECT *
FROM cc_restaurants_menu
WHERE menu_id = "7"
UNION ALL
SELECT *
FROM cc_restaurants_menu
WHERE menu_id = "50"
UNION ALL
SELECT *
FROM cc_restaurants_menu
WHERE menu_id = "50"
ORDER BY FIELD (menu_id,"7","50","50")
Or build up the required menu ids in a sub query which you then join against the main table.
SELECT cc_restaurants_menu.*
FROM cc_restaurants_menu
INNER JOIN
(
SELECT 7 AS a_menu_id UNION ALL SELECT 50 UNION ALL SELECT 50
) sub0
ON cc_restaurants_menu.menu_id = sub0.a_menu_id
ORDER BY FIELD (cc_restaurants_menu.menu_id,"7","50","50")
Generating the first query with implode would be done something like this:-
$sql = "SELECT * FROM cc_restaurants_menu WHERE menu_id = '".implode("' UNION ALL SELECT * FROM cc_restaurants_menu WHERE menu_id = '", id_array)."' ORDER BY FIELD (menu_id,'".implode("','", id_array)."')";
and generating the 2nd query with implode would be done something like this:-
$sql = "SELECT cc_restaurants_menu.* FROM cc_restaurants_menu INNER JOIN (SELECT ".implode(" AS a_menu_id UNION ALL SELECT ", id_array) AS a_menu_id ) sub0 ON cc_restaurants_menu.menu_id = sub0.a_menu_id ORDER BY FIELD (cc_restaurants_menu.menu_id,".implode(",", id_array).")";

Mysql - get last post from category

I have this structure (tables) of forum
I want to select last post (row from forum_post table) from category.
SQL so far:
SELECT * FROM table_post
WHERE topic_id = (SELECT MAX(id) FROM table_topic WHERE category_id = {$id})
ORDER BY id ASC LIMIT 1
Question: How to modify this select to achieve my goal?
Assuming that "last" means the biggest id, I would suggest order by and limit:
select fp.*
from forum_post fp join
forum_topic ft
on fp.topic_id = ft.id
where ft.category_id = $id
order by fp.id desc
limit 1;

How to echo the post's content

I have two tables like this:
posts table:
post_id subject
1 abc
2 def
and contents table, of which the post_id column is the foreign key:
content_id post_id content date
1 1 main content 2014-07-31 03:02:00
2 1 reply one 2014-07-31 03:03:20
3 1 reply two 2014-07-31 03:06:32
As you can see, the contents table stores both the post's content and its possible repli(es). Here, in this example, the post_id # 1 has its main content and two replies.
What I want to do is to echo the subject and its content only, but not the replies. So I have coded the query like this:
$query = "SELECT subject, content
FROM posts As p
INNER JOIN contents AS c USING (post_id)
ORDER BY post_id DESC";
$result = mysqli_query ($dbc, $query)
while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
echo "{$row['content']}n\";
}
Then you know what?. It echoes out the latest content of the post, which is the content_id # 3. However, what I wanted to do is to echo the post's content, which is the oldest content_id of the post_id # 1.
Can you help me, please?
UPDATED
It basically selects the minimum date per post in a subquery and uses it as a key for the "normal" query to look for.
SELECT distinct subject, content FROM content c
JOIN post p
on c.post_id = p.post_id
WHERE cast(c.post_id as char)+cast(c.contentdate as char)in
(
SELECT
cast(p.post_id as char)+cast(min(c.contentdate) as char) as KeyValue
FROM post p
INNER JOIN content c on p.post_id = c.post_id
GROUP BY p.post_id
)
This returns me:
subject | content
----------------------
asd | main content
def | main content
MIN(DATE) has to be content, so you need to GROUP the id with the DATE
Join both tables on the basis of post_id and then group on the basis of min(date)
$query = "SELECT p.post_id, p.subject, c.content, c.date
FROM posts p
INNER JOIN contents c on p.post_id = c.post_id
WHERE date = (select min(date)
from contents ct
where ct.post_id = p.post_id
)
GROUP BY post_id,subject,content, date
ORDER BY post_id DESC";
$result = mysqli_query ($dbc, $query)
while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {
echo "{$row['content']}n\";
}
Try this
$query = "SELECT subject, content
FROM posts As p
INNER JOIN contents AS c USING (post_id)
ORDER BY date ASC, post_id DESC";
You need to order results by content_id (or date) too. So the sql query might look like this:
$query = "SELECT subject, content
FROM posts As p
INNER JOIN contents AS c USING (post_id)
ORDER BY post_id DESC, content_id ASC";
And, of course, I assume that the main content has added to database before the replies and you will not alter the row indexes which might lead to situation where the first row with certain post_id isn't the actual content.
So, if you want to print out everything you need to do something in your code. You need to print only the first ones of rows with same post_id:
$last_post_id = 0;
while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
if ($last_post_id != $row['post_id']) {
echo "{$row['content']}n\";
}
$last_post_id = $row['post_id'];
}
After testing all the answers here, I chose the answer of #NoobEditor. However, I have to make it clearer as follows:
$query = "SELECT p.post_id, p.subject, c.content, c.date
FROM posts p
INNER JOIN contents c on p.post_id = c.post_id
WHERE date = (select min(date)
from contents c
where c.post_id = p.post_id
)
GROUP BY c.post_id
ORDER BY p.post_id DESC";
$result = mysqli_query ($dbc, $query)
In which I made it clearer at the GROUP and ORDER BY functions. And use c as alias for contents table, but not need to use c and ct
while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {
echo "{$row['content']}n\";
}

Revising SQL query to return user's own posts?

Currently, the query works fine and does as its supposed to do. However, I'd like to change the query so it retrieves the user's own posts in addition to the other posts. How can I do this? I've tried things like OR P.author = $_SESSION['username'] but it seems this results in each of the user's own posts being echoed multiple times.
$gtPsts = "SELECT P.id, P.subid, P.author, P.post, P.access, P.date, F.friends, F.following, F.f1, F.f2, F.status
FROM posts AS P, friends AS F
WHERE (F.f1 = '$_SESSION[username]' AND F.f2 = P.author AND F.status = 1 AND P.access = 'Public' OR P.access = 'Friends')
OR (F.f2 = '$_SESSION[username]' AND F.f1 = P.author AND F.status = 1 AND P.access = 'Public' OR P.access = 'Friends')
OR (F.f1 = '$_SESSION[username]' AND F.f2 = P.author AND F.following = True AND P.access = 'Public' OR P.access = 'Following')
ORDER BY P.date DESC LIMIT 20";
Structure of table is as follows: id (int), subid (int), author (varchar), post (longtext), access (varchar), date (datetime).
You get the users' own posts multiple times because the query joins your two tables posts and friends. So if you filter for (P.author = $_SESSION['username']), you get one of his posts together with each item in the friends table.
You could use a workaround. If your friends table has a primary/unique key, let's say id, you could use OR (P.author = '$_SESSION[username]' AND F.id = (SELECT id FROM friends LIMIT 1)). There must be a more performant way, but this should already help.

join two tables order by date and display results

I'm trying to make a function kinda similar to facebook's notification window. Their function seems to combine any kind of event and display them after date.
So i have 2 tables :
Article and comments.
both have 2 similar rows : uniquepostowner and date_posted.
I want to join them up and display them one after another.
Example :
User A has posted a comment (04.05.2012 5:30)
User B Has posted a comment (04.05.2012 6:30)
User C has written an article (04.05.2012 7:30)
user D has posted a comment (04.05.2012 8:30)
However, i'm struggling with both joining these 2 and displaying the results.
Reading others with similar scenarios ive tried this as a query:
$sesid = $_SESSION['user_id'];
$sql = "SELECT X.* FROM ( SELECT * FROM `article` WHERE uniquepostowner = {$sesid} UNION SELECT * FROM `comments` WHERE uniquepostowner = {$sesid} ) X ORDER BY X.`date_posted`";
$result = mysql_query($sql);
Then trying to fetch the results like this:
while($row = mysql_fetch_array($result))
{
echo $row['article.id'];
}
Tables:
**article**:
id
title
content
uniqueuser
date_posted
full_name
uniquepostowner
**comments**:
id
pid (same as article.id)
date_posted
content
full_name
uniquepostowner
there are more rows to these tables, but they are irrelevant.
But no success. Any help is greatly appreciated as always! :)
Currently i'm trying this, but its not doing what i want.
$sql = "SELECT * FROM article a INNER JOIN comments c WHERE a.uniquepostowner = {$sesid} AND c.uniquepostowner = {$sesid}
ORDER BY a.date_posted DESC , c.date_posted DESC ";
I think this is what you need:
UPDATED:
$sesid = $_SESSION['user_id'];
$sql = "
SELECT
X . *
FROM
(SELECT
id,
date_posted,
content,
full_name,
uniquepostowner,
'article' AS type
FROM
article
WHERE
uniquepostowner = {$sesid} UNION SELECT
id,
date_posted,
content,
full_name,
uniquepostowner,
'comment' AS type
FROM
comments
WHERE
uniquepostowner = {$sesid}) X
ORDER BY X.date_posted
";
$result = mysql_query($sql);
And you can iterate with:
while($row = mysql_fetch_array($result))
{
if($row['type']=='article'){
echo "User " . $row['full_name'] . " has written an article (".$row['date_posted'].")<br>";
} else {
echo "User " . $row['full_name'] . " has posted a comment (".$row['date_posted'].")<br>";
}
}
You can check it out at:
http://sqlfiddle.com/#!2/38778/8
you should try to rephrase your sql to only use the columns both tables have in common:
SELECT uniquepostowner,date_posted FROM `article` WHERE uniquepostowner = {$sesid}
UNION
SELECT uniquepostowner,date_posted FROM `comments` WHERE uniquepostowner = {$sesid}
ORDER BY date_posted
there are some more examples in the mysql manual.
You must make the collumns on each query of the union equal:
SELECT X.* FROM ( SELECT **uniquepostowner** FROM `article` WHERE uniquepostowner = {$sesid} UNION SELECT **uniquepostowner** FROM `comments` WHERE uniquepostowner = {$sesid} ) X ORDER BY X.`date_posted`
This is just a example, in the union, both queries must return the same amount of fields, I sugest that you return only the filds that both tables have in commom.
Maybe I'm missing the point, but wouldn't this solve the problem:
SELECT articles.*, comments.* FROM articles, comments WHERE articles.uniqueuserid = $userId AND comments.postId = articles.Id ORDER BY articles.date_published DESC
Ofc all table and field names are would need adjustments to fit with your code.
What it does, is basically it loads all articles with uniquepostowner or whatever your name is and corresponding comments sorted by publish date.
Is this what you are after?
EDIT
Actually, comments and articles are spearate, and you want to display them side by side? In that case why don't you create 'events' table, which holds the date, the owner, the type (article/comment/like/photo/anything) and id of corresponding item and use that to generate your feed?

Categories