Joining 4 tables with Mysql and Codeigniter - php

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');

Related

codeigniter inner join not working as expected

I have a inner join query as below,
SELECT * FROM shop_offer so INNER JOIN shop s ON s.shop_id = so.shop_id INNER JOIN city c ON c.city_id = s.city_id INNER JOIN locality l ON l.locality_id = s.locality_id INNER JOIN category ca ON ca.category_id = s.category_id WHERE so.offer_discount >= 10 AND so.publish = 1
While executing the above query in phpmyadmin, the result showing only one row as expected.
But when i tried this query in codeigniter, the result showing 3 rows. My codeigniter code is,
$this->db->select('*');
$this->db->from('shop_offer as so');
$this->db->join('shop as s', 's.shop_id = so.shop_id');
$this->db->join('city as c', 'c.city_id = s.city_id');
$this->db->join('locality as l', 'l.locality_id = s.locality_id');
$this->db->join('category as ca', 'ca.category_id = s.category_id');
$this->db->where(array('so.offer_discount >=' => 10, 'so.publish' => 1));
$query = $this->db->get();
What is the problem in codeigniter code. I am new in codeigniter. Is thre any way to solve this error.
You can also try running the query like this,
$this->db->query("SELECT * FROM shop_offer so
INNER JOIN shop s ON s.shop_id = so.shop_id
INNER JOIN city c ON c.city_id = s.city_id
INNER JOIN locality l ON l.locality_id = s.locality_id
INNER JOIN category ca ON ca.category_id = s.category_id
WHERE so.offer_discount >= 10 AND so.publish = 1");

PHP SQL how the get the exact count from a table

I have two tables with the following columns:
FAMILY - id, ...
PRODUCTS - id, idfamily, type, ...
FAMILY & PRODUCTS are connected with family.id = products.idfamily.
I'm doing pagination over families with filters based on products types, so I'm trying to get the exact count of FAMILY containing almost one product with a specific type.
First query is ok, I get all the families:
if (!isset($_GET['type']) || $_GET['type'] == 'all') {
$query_family=mysql_query("SELECT * FROM family");
}
$count=mysql_num_rows($query_family);
// result = 166
Unfortunately, the following query is wrong:
} else {
$query_family=mysql_query("
SELECT * FROM family f LEFT JOIN products p ON f.id = p.idfamily
WHERE p.type = '$_GET[type]'
");
}
$count=mysql_num_rows($query_family);
// result = 500+
it's wrong because I get all the products with a type, but I'm trying to get the number of families containing products with the selected type ($_GET[type]).
Thank you
You should have
SELECT distinct f.id from family f LEFT JOIN products p on f.id = p.idfamily WHERE p.type = '$_GET[type]' in the second query
I think.
SELECT COUNT(*) as nbr FROM family
INNER JOIN products ON products.idfamily = family.id
WHERE product.type = ".intval($_GET['type'])."
GROUP BY family.id
Avoid the mysql_ driver, use PDO or mysqli instead. Don't forget to protect you from sql injections too.
To get the count of families with a specified type, use
SELECT * FROM family f INNER JOIN products p ON f.id = p.idfamily
WHERE IFNULL(p.type, 'notspecified') = '$_GET[type]'
With INNER JOIN instead of LFET JOIN you get only rows where a connection between f.id and p.idfamily exist. By LEFT JOIN, all family rows are returned with NULL values in the fields of product table.
So when p.type is NULL, your p.type = '$_GET[type]' evaluates always to NULL, and your filtering will not work as expected. For this reason, use IFNULL.
You can try below code:
$query_family=mysql_query("
SELECT COUNT(f.id) AS cnt FROM family f
INNER JOIN products p ON f.id = p.idfamily
WHERE p.type = '$_GET[type]'");
Also try to use mysqli not mysql.
And you don't have to use mysql_num_rows, you can get the right number directly from mysql:
$query = "SELECT COUNT(DISTINCT f.id) ".
"FROM family f ".
"LEFT JOIN products p ON f.id = p.idfamily ".
"WHERE p.type = '".$_GET['type']."'";
Use INNER JOIN instead of LEFT.

Doctrine don't return all result - DQL, JOIN

This is my repository's function's code:
public function findLatest($count, $page)
{
return $this->getEntityManager()
->createQuery
('
SELECT
n.id, n.createdAt, n.title, n.titleCanonical, n.entry, n.movie,
c.title as category,
i as images,
COUNT(com.id) as numberOfComments
FROM WisJaCoreBundle:News n
JOIN n.category c
LEFT JOIN WisJaCoreBundle:Image i
WITH i.target = \'Article\' AND i.targetId = n.id AND n.movie IS NULL
LEFT JOIN WisJaCoreBundle:Comment com
WITH com.target = \'Article\' AND com.targetId = n.id
ORDER BY n.createdAt DESC
')
->setFirstResult($page * $count - $count)
->setMaxResults($count)
->getResult();
}
In table News I have a few records, but I get only one... I found problem, it's this fragment
COUNT(com.id) as numberOfComments
When I replace this for example:
n.id as numberOfComments
then all working good and I get all result. Why "COUNT" destroy my query?
EDIT------------------------------------------
I still don't know why that construction doesn't works, but problem is in same SQL, instead only "COUNT" had put nested query like this:
SELECT
n.id, n.createdAt, n.title, n.titleCanonical, n.entry, n.movie,
c.title as category,
i as images,
(SELECT COUNT(com.id) FROM WisJaCoreBundle:Comment com WHERE com.target = \'Article\' AND com.targetId = n.id) as numberOfComments
FROM WisJaCoreBundle:News n
JOIN n.category c
LEFT JOIN WisJaCoreBundle:Image i
WITH i.target = \'Article\' AND i.targetId = n.id AND n.movie IS NULL
ORDER BY n.createdAt DESC
So, problem is solved :)

Making query with multiple join's

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

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