How to use Multi table queries in Laravel without using Eloquent Relationships - php

I am using Laravel to create API for my app, later it will be integrated with react front-end. I have two tables, Post & Comment. Post table contains info about posts & comment table contains the comments data about each post. Below is there structure,
Post Table
post_id (Primary Key)
post_title
post_description
Comment Table
comment_id (Primary Key)
comment_text
post_id (Foreign Key)
I need to take post_id, post_title from post table and total no of comments on each post from comment table & want the json data to be showed like this
{
"post_id": 1,
"post_title": "some title",
"total comments": "4"
},
I know how to write sql queries for these but just having issue with showing the data like the above. Below is the code which I am using.
$allPostQuery= DB::select('select * from post');
foreach($allPostQuery as $allPostQuery)
{
$postId= $allPostQuery->post_id;
$totalCommentsQuery= DB::select('select count(comment_id) as totalComments from comment where post_id=:postId',["postId" => $postId ]);
}
return \Response::json([$allPostQuery,$totalCommentsQuery]);
But thats not working. I am confused about the looping of post ids to get total comments for each post. Do I have to do this in front-end using react foreach loop? Anyone can suggest any help. Thanks

As per your question you just need the Post ID, TITLE and Count of the Comments of each posts:
$query = DB::select('
SELECT
p.post_id,
p.title,
c.total AS totla_comments
FROM posts p
INNER JOIN
(
SELECT post_id, COUNT(post_id) AS total FROM comments WHERE comments.post_id = post_id
GROUP BY post_id
) c
ON p.post_id = c.post_id
');
echo json_encode($query);
Use json_encode (Laravel has ->json() function) if you want the data return should be in JSON format.
Looking at your approach:
First you query the post
You loop the post again and query the comments
This will impact your performance speed and should be avoided.

Related

laravel get data when give id not match with join table id

here is my category table data
id
1
2
6
7
when in my post bale I join with this category table
here is my post table sample data
ID = 1,
name = 'hellow'
category id = 4 (i join with category table but selected category is
deleted)
here is my index SQL query (when categy_id match with the category.id) then only its fetch
$post = DB::table('posts)->join('category','posts.category_id','categories.id')-.paginate(10);
for some reason, the selected category can be deleted so I try to get category deleted post data
here is my query
$cpost = DB::table('posts')->join('categories','posts.category_id', '!=' ,'categories.id')->select('post.*')->paginate(5);
but above query duplicate post data based on available category data
i want all post data which are category id is not matched with in category table id how can i get that ?
Try this. Key is the leftJoin instead of default innerJoin (join).
// posts without assigned or existing category
$posts = \DB::table('posts')
->leftJoin('category','posts.category_id','categories.id')
->whereNull('categories.id')
->paginate(10);
why are you doing a join for this? you already have category id stored in your post table.
$cpost = DB::table('posts')->where('category_id','!=', $category_id)->paginate(5);
Just try it:
$cpost = DB::table('posts')
->join('categories','posts.category_id', '=' ,'categories.id')
->select('post.*', 'categories.*')
->whereNotIn('posts.category_id', DB::raw('select id from categories'))
->paginate(5);

How can i get one table id values to another table

I have a two tables in my database. One is "blog" second is "comment".
Blog table have this structure
id, title, text, writer_id, created_at, updated_at
Comment table have this structure
id, blog_id, text, commenter_id, created_at, updated_at
I want to get id value from blog table as in comment table in the form of blog_id . How can i get the same value.
Example:
One blog posted. blog table have these values.
id: 1
title: hi i m blogger
text: how are you
writer_id: 5 (same User id)
created_at:25 feb
updated_at: 25 feb
Blog posted . One commenter comes and comment on this post. Value should be comes as like this in comment table
id=1
blog_id:1
text: ok i know
created_at:25 feb
updated_at: 25 feb
id of blog table and blog_id of comment table should be same. How can i do this with query or php code?.
Try This Query
SELECT b.id, c.`text`,..... FROM blog b
LEFT JOIN comment c
ON b.id = c.blog_id
ORDER BY commenter_id DESC ;
if you want for perticular blog so add WHERE CONDITION
SELECT b.id, c.`text`,.... FROM blog b
LEFT JOIN comment c
ON b.id = c.blog_id
b.id = 'Your ID'
ORDER BY commenter_id DESC ;
First of all you have to put foreign constraint that the value of column "Blog_Id" in table comment should always be from table "blog"
select * from blog bg inner join comment cm on cm.blog_id = blog.id this is the query for retrieving what you want.

How to write IF ELSE statements in MySQL

I have tables posts and users
basically i want to query if the column privacy of posts table is 0 it means post is public and i want to show this to everyone. but if privacy column is 1,2,3,4 it means this post is only for users with ID 1, 2, 3 and 4
This is not a conditional problem it's a sql join through table association problem.
You need to create a join table that associates a post to a user. You can then use a join to select posts based upon their assignment to a user.
The SQL might look something like this
To select posts assigned to user ID = 4
SELECT * FROM `posts`
LEFT JOIN `posts_users` ON (`posts`.`id` = `posts_users`.`post_id`)
WHERE `posts_users`.`user_id` = 4;
You have also made the assumption that if a post has no users assigned to it, then it's a public post. That requires a check for NULL associations.
SELECT * FROM `posts`
LEFT JOIN `posts_users` ON (`posts`.`id` = `posts_users`.`post_id`)
WHERE `posts_users`.`user_id` IS NULL;
If you want to find both public and associated posts, then you use a logical OR to match both rules.
SELECT * FROM `posts`
LEFT JOIN `posts_users` ON (`posts`.`id` = `posts_users`.`post_id`)
WHERE `posts_users`.`user_id` = 4
OR `posts_users`.`user_id` IS NULL;

MYSQL Select Statement with IN Clause and Multiple Conditions

There might be an easy solution here, but it seems to have me tripped up. I'm trying to query a table based on an array of values in two columns. Here is the pertinent table structure and sample data
comment table
id, userId, articleId .... etc etc
article table
id, userId .... etc etc
Data: UserIds = 3, 10. ArticleIds = 1, 2
Let's say I'm trying to find all the comments for a particular set of article IDs: 1,2
I can easily use this query
select * from comments WHERE articleId IN(1,2)
However, here is where it gets complex. I have a query that executes prior to the comments query that determines the appropriate article IDs. Those IDs are in an array. Also in an array are the corresponding user IDs for each article.
What I want to do now is query the comments table for only the articles in the array (1,2) AND only for those comments made by the original author (3, 10).
The simple query above will bring back all the comments for articleId 1 and 20. So for example I can't figure out where to add another conditional that says onyl comments for articleId 1, 20 AND corresponding userId, 3, 10.
Any help or suggestions would be much appreciated!
I think the simplest way is to write:
SELECT comments.*
FROM articles
JOIN comments
ON articles.id = comments.articleId
AND articles.userId = comments.userId
WHERE articles.id IN (1, 2)
;
The AND articles.userId = comments.userId clause is what enforces your "only for those comments made by the original author" requirement.
Alternatively, you can use an EXISTS clause:
SELECT *
FROM comments
WHERE articleId IN (1, 2)
AND EXISTS
( SELECT 1
FROM articles
WHERE id = comments.articleId
AND userId = comments.userId
)
;
or a single-row subquery:
SELECT *
FROM comments
WHERE articleId IN (1, 2)
AND userId =
( SELECT userId
FROM articles
WHERE id = comments.articleId
)
;
Have you tried just
select * from comments WHERE articleId IN(1,2) and authorId in (3,10)
If not, please update your question why it's so.
You can add as many IN statements as you want:
select * from comments WHERE articleId IN(1,2) AND userId IN (3,10)
Can't you just make the query that runs first a subquery within your stated query:
SELECT * FROM `comments` WHERE `articleId` IN(1,2) AND `userId` IN (__subquery__)
-- you can use subquery
select * from comments WHERE articleId IN(1,2)
and userId in ( select userId from article where id in (1,2) )

MYSQL Join Statement - im lost

OK, I need to get some data from multiple tables, all of which have a key.
Projects (key:id)
Projects_users (key:project_id,user_id)
Users (key:id)
Basically each project can have N users on it. I need to get all the users that are in each project in a formatted response.
For instance:
projects = {[
1: {
'title':'Project 1',
'users': [
1: { id: 23, name:'john' },
2: { id: 55, name:'sally' }
]
}
2: {
'title':'Project 2',
'users': [
1: { id: 41, name:'jeff' },
2: { id: 55, name:'sally' }
]
}
]}
Also, I understand I can do this in PHP with multiple MYSQL statements. Would that be faster and do the concatenation in PHP, or letting MYSQL do this be more efficient / quick.
You can use following statement to get the desired data:
SELECT `Projects`.*, `Users`.* FROM
`Projects` JOIN (
`Projects_users` JOIN
`Users`
ON `Projects_users`.`user_id` = `Users`.`id`
)
ON `Projects`.`id` = `Projects_users`.`project_id`
ORDER BY `Projects`.`id`
After that, you can traverse the resulting table in single pass and build the array you want.
I haven't tried this, but it should be close to what you're looking for:
select p.title, u.name
from projects p inner join users u
on p.id = u.id
order by p.title
You need the "join" to get the data .. but use PHP to format it.
PS:
"projects" is one table, "users" is a second table ... and the "projects" table needs to hold "foreign keys" for user IDs 23, 55 and 41.
MySql won't be able to return data in a tree-like structure like you want. You can do this in two ways:
Get all projects in one data set and all users associated to those projects on a second data set. You would have to write the code that generates the JSON objects you need.
Just get one data set doing an inner join of the project's table with the user's table. You will get repeated information on many columns but you will get everything in one sql statement. You could then iterate through the result set and generate the structure you need.
If you need help with the inner join, it would be something like:
select p.title, u.id, u.name
from projects p
inner join project_users pu on pu.project_id=p.id
inner join users u on u.id=pu.user_id

Categories