Making query with multiple join's - php

I'm now learning php and codeigniter and now I want to combine query to be fast and effective. I have made all, but haven't joined the last table...
I have 4 tables: posts, users, post_categories, categories;
And what I want to get:
All posts
User info using usr_id
Get all categories id from post_categories using cat_ids
And get each name of category using id_*
This is what I end up... it's not complete because I've got stuck with getting categories name for each of id_*
$data = $this->db->select('p.*, u.nickname, u.usr_status, u.usr_rating, pc.*')
->from('posts p')
->join('users u', 'p.usr_id = u.id', 'left')
->join('post_categories pc', 'p.cat_ids = pc.id', 'left')
->limit($limit, $start)
->order_by('p.id', 'desc')
->where('p.active', 1)
->get()
->result_array();
Anyone could help me to end up this query in codeigniter?
edit:
in post_categories: id_1 always will be... but id_2 and id_3 could stay as NULL(default value)

Something like the following SQL query should work for you...
SELECT
posts.*,
users.nickname, users.user_status, users.usr_rating,
c1.category as category_1,
c2.category as category_2,
c3.category as category_3
FROM posts
INNER JOIN users ON user.id = posts.user_id
INNER JOIN post_dategories ON post_categories.id = posts.cat_ids
INNER JOIN categories c1 ON post_categories.id_1 = c1.id
LEFT JOIN categories c2 ON post_categories.id_2 = c2.id
LEFT JOIN categories c3 ON post_categories.id_3 = c3.id
WHERE posts.active = 1
NOTE: LEFT JOIN on c2 and c3 because you said they were optional

Related

Laravel 6, MYSQL - How to Left Join a Sub Query with GroupBY using Laravel Querybuilder or Model Eloquent?

Im tried this to work it using Laravel Eloquent but i cant get exact query. So i make a raw query to get the data i want. Any one help me how to convert this into laravel eloquent or Query builder?
SELECT users.*,
chat.*
FROM users
LEFT JOIN
(SELECT a.customer_id,
a.time,
b.content
FROM
(SELECT customer_id,
MAX(datetimestamp) TIME
FROM chat_messages
GROUP BY customer_id) a
JOIN chat_messages b ON a.customer_id = b.customer_id
AND a.time = b.datetimestamp) chat ON users.id = chat.customer_id
WHERE users.customer_role != 0
ORDER BY TIME DESC
I think you are trying to get latest chat message for each user , your query can be rewritten using left join to pick the latest record per group and it would be easier to transform such query in laravel's query builder format
SQL
select u.*,c.*
from users u
join chat_messages c on u.id = c.customer_id
left join chat_messages c1 on c.customer_id = c1.customer_id and c.datetimestamp < c1.datetimestamp
where c1.customer_id is null
and u.customer_role != 0
order by c.datetimestamp desc
Query Builder
DB::table('users as u')
->select('u.*, c.*')
->join('chat_messages as c', 'u.id', '=', 'c.customer_id' )
->leftJoin('chat_messages as c1', function ($join) {
$join->on('c.customer_id', '=', 'c1.customer_id')
->whereRaw(DB::raw('c.datetimestamp < c1.datetimestamp'));
})
->whereNull('c1.customer_id')
->where('u.customer_role','!=',0)
->orderBy('c.datetimestamp', 'desc')
->get();
Reference:Laravel Eloquent select all rows with max created_at

Nested joins in Codeigniter

How to run this sql query in Codeigniter framework?
SELECT users.*,
GROUP_CONCAT(category.title SEPARATOR ',') as title
FROM users
LEFT JOIN (
procducts as pr
INNER JOIN category ON pr.category_id =category.id
)
ON (users.id=pr.user_id)
GROUP BY users.id
using Active Record (Query Builder Class) in Codeigniter without using db->query
The Codeigniter docs explain a join like follows:
join($table, $cond[, $type = ''[, $escape = NULL]])
there is no documentation on nested join support. So you could create a query like:
$this->db->select('users.*, GROUP_CONCAT(category.title SEPARATOR ',') as title')
->from('users')
->join('procducts as pr INNER JOIN category ON pr.category_id =category.id','users.id=pr.user_id','left')
->group_by('users.id');
$query = $this->db->get();
i use this code
$this->db->select("
users.*,GROUP_CONCAT(category.title SEPARATOR ',')
as title FROM users LEFT JOIN
(procducts as pr INNER JOIN category ON
pr.category_id =category.id)
ON (users.id=pr.user_id)");
$this->db->group_by("users.id");
and this code it's ok,and without any problem .

Joining 4 tables with Mysql and Codeigniter

I have 4 tables, that's all in a relationship, yes they love each other :p
Products
Product Categories
Product Category Relationships
Product Images
I want to join these 4 tables in one query, here is my Codeigniter code to do this;
function list_products($limit = 10, $offset = 0, $category)
{
$this->db->select('p.url, p.name, p.title, i.image');
$this->db->from('products p');
$this->db->join('product_categories c','c.id = r.category_id',
'left');
$this->db->join('product_category_relations r',
'r.category_id = c.id','left');
$this->db->join('product_images i',
'p.id = i.product_id AND i.default = 1','left');
$this->db->where('c.url',$this->category_url.$category);
$this->db->limit($limit,$offset);
return $this->db->get()->result();
}
When i execute this function / query, the result is an error about defining "r".
Unknown column 'cms_r.category_id' in 'on clause'
The query:
SELECT p.url, p.name, p.title, i.image FROM
(cms_products p) LEFT JOIN cms_product_categories c ON c.id =
cms_r.category_id LEFT JOIN cms_product_category_relations r ON
r.category_id = c.id LEFT JOIN cms_product_images i ON
p.id = i.product_id AND i.default = 1 WHERE c.url =
'kategori/yilbasi' LIMIT 12
Can you help me?
You assign r to be similar to product_category_relations after you use it.
Here you write:
$this->db->join('product_categories c','c.id = r.category_id','left');
But what is r? You answer this question only in the next statement.
$this->db->join('product_category_relations r','r.category_id = c.id','left');
Provide sample SQL Create script, if you want concrete answer.
#Edward Ruchevits your query does not join because of r.category_id define after joining of product_category_relations r, you need Relationships between products and product_categories then your query something be like
$this->db->join('product_categories c','c.product_id = p.id','left');

Getting multiple counts from two joined tables in MySQL

So I have two tables, categories and designs. I want to construct a query that will fetch all categories, along with the count of any sub categories (categories.parent_id equal to the categories.id) AND the count of any designs (design.category_id equal to categories.id)
If I try to just get one of these counts, everything works fine, but when I try for both with the following code, the count for both is the same number (and not the correct number) for either.
$this->db->select('categories.id AS id, categories.parent_id AS parent_id, categories.title AS title,
categories.description AS description, categories.img_path AS img_path, COUNT(designs.id) AS design_count,
COUNT(sub_categories.id) as sub_category_count');
$this->db->from('categories');
$this->db->join('designs', 'categories.id = designs.category_id', 'left');
$this->db->join('categories as sub_categories', 'categories.id = sub_categories.parent_id', 'left');
$this->db->group_by('categories.id');
Any help will be much appreciated, cheers!
Assuming that the root categories do not contain designs, here is the query that returns the necessary information:
SELECT category.id, category.title, subcategory.id, designs.id
FROM categories category
LEFT JOIN categories subcategory ON category.id = subcategory.parent_id
LEFT JOIN designs ON subcategory.id = designs.category_id
WHERE category.parent_id IS NULL
Now all you need to do is to apply grouping:
SELECT category.id, category.title, COUNT(DISTINCT subcategory.id), COUNT(designs.id)
FROM categories category
LEFT JOIN categories subcategory ON category.id = subcategory.parent_id
LEFT JOIN designs ON subcategory.id = designs.category_id
WHERE category.parent_id IS NULL
GROUP BY category.id, category.title
The key here is the use of COUNT(DISTINCT ...).
SELECT c.id,c.title,
IFNULL(sc.counted,0) AS subcategories,
IFNULL(d.counted,0) AS designs
FROM categories c
LEFT JOIN
( SELECT parent_id,COUNT(*) AS counted
FROM categories GROUP BY parent_id ) sc
ON c.id=sc.parent_id
LEFT JOIN
( SELECT category_id,COUNT(*) AS counted
FROM designs GROUP BY category_id ) d
ON c.id=d.category_id
WHERE c.parent_id IS NULL ;
should get you the desired numbers as raw SQL.

SQL Join question, return null if second table is empty

I have 2 tables.
table 1 (projects): id, name, type
table 2 (project_ratings): project_id, rating
Some projects don't have ratings.
SELECT `p`.`id`, `p`.`name`, AVG(pr.rating) FROM (`projects` p) JOIN `project_ratings` pr ON `p`.`id` = `pr`.`project_id` WHERE `p`.`type` = 'group' OR `p`.`type` = 'user';
I want to return all projects, and return NULL if there aren't any ratings. This query returns only the ones with ratings.
I tried left join, right join, full join, still same thing.
Using CodeIgniter Active Records:
$this->db->select("p.id, p.name, AVG(pr.rating)");
$this->db->from('projects p');
$this->db->join('project_ratings pr', 'p.id = pr.project_id');
$this->db->where('p.type', 'group');
$this->db->or_where('p.type', 'user');
$res = $this->db->get();
what am I missing?
When using an aggregate function (AVG() in this case), you need to specify a GROUP BY clause with the non-aggregate fields, eg
GROUP BY p.id, p.name
To ensure all project references are present regardless of joined ratings, use a LEFT JOIN.
The sql that you want would be
SELECT *
FROM projects
LEFT OUTER JOIN project_ratings ON projects.id = project_ratings.project_id
I'm not certain how to do that with code igniter.
Try this:
$this->db->select("p.id, p.name, AVG(pr.rating) as average_rating");
$this->db->from('projects p');
$this->db->join('project_ratings pr', 'p.id = pr.project_id', 'left');
$this->db->where('p.type', 'group');
$this->db->group_by('p.id');
$this->db->or_where('p.type', 'user');
$res = $this->db->get();
If there is no rating, average_rating will be NULL.
Query should be:
SELECT `p`.`id`, `p`.`name`, AVG(pr.rating)
FROM (`projects` p)
LEFT OUTER JOIN `project_ratings` pr ON `p`.`id` = `pr`.`project_id`
WHERE `p`.`type` = 'group' OR `p`.`type` = 'user';
(I don't know how to do that in CodeIgniter :)
You can get an outer join by do this:
$this->db->join('project_ratings pr', 'p.id = pr.project_id', 'outer');

Categories