Laravel 5 Join table and select Popular Category - php

I have 2 tables, category and service
category_table
+----+--------------+
| id | category |
+----+--------------+
| 1 | category_1 |
| 2 | category_2 |
+----+--------------+
service_table
+----+--------------+-----------+
| id | service | cat_id |
+----+--------------+-----------+
| 1 | service_a | 1 |
| 2 | service_b | 1 |
| 3 | service_c | 1 |
| 4 | service_d | 2 |
+----+--------------+-----------+
I want to get the category count from the service table and display the result using the category name and limit it to 5 most used category
The desired result:
category name | category count
category_1 | 3
category_2 | 1
Seems like i have to join or leftjoin these table, but it is pretty confusing for me

You are right, you must use join's. You can rewrtie it with Eloquent, or use DB::raw() Try this:
SELECT c.category, COUNT(*) AS category_count FROM category_table c LEFT JOIN service_table s ON(c.id = s.cat_id) GROUP BY s.cat_id ORDER BY category_count DESC LIMIT 5;
P.S. I don't check it, but must work. Good tutorial about joins

DB::table('category_table')
->leftJoin('service_table', 'category_table.id', '=', 'service_table.cat_id')
->select(DB::raw('category_table.category,count(service_table.cat_id) as category_count'))
->groupBy('service_table.cat_id')
->order_by('category_count', 'desc')
->take(5)
->get();

Related

Combine whereRaw() with leftjoin() using eloquent

I am trying to join 2 tables and get the latest unique results using whereRaw() and leftJoin() with Laravel eloquent.
I have 2 tables:-
skills table (has timestamps):-
| id| name | icon |
| 1 | skill 1 | skill1.png |
| 2 | skill 2 | skill2.png |
| 3 | skill 3 | skill3.png |
scores table (has timestamps):-
| id| player_id | skill_id | score |
| 1 | 1 | 1 | 1 |
| 2 | 1 | 2 | 1 |
| 3 | 1 | 3 | 1 |
| 4 | 1 | 2 | 2 |
I would like to return all skills but only the latest entry(by id), so for the above snippet I should get:-
| id| player_id | name | skill_id | score |
| 1 | 1 | skill 1 | 1 | 1 |
| 3 | 1 | skill 3 | 1 | 1 |
| 4 | 1 | skill 2 | 2 | 2 |
I can get the latest unique records by using:
return SkillScores::where('player_id', $this->id)
->whereRaw('id in (select max(id) from skills group by (name))')
->get();
I can get the skill names by using:-
return SkillScores::where('player_id', $this->id)
->leftJoin('skills', 'skill_scores.skill_id', '=', 'skills.id')
->get();
but when I combine them I get an SQLSTATE[23000] error
return SkillScores::where('player_id', $this->id)
->whereRaw('id in (select max(id) from skills group by (name))')
->leftJoin('skills', 'skill_scores.skill_id', '=', 'skills.id')
->get();
Can anyone help me figure out what is going wrong?
EDIT:-
It turns out that the SQLSTATE[23000] error is occuring because I have an id column in both tables and I havent told it which one I am referencing, the below fixes the issue and gives me the correct result.
return SkillScores::where('player_id', $this->id)
->whereRaw('skill_scores.id in (select max(skill_scores.id) from skill_scores group by (skill_id))')
->leftJoin('skills', 'skill_scores.skill_id', '=', 'skills.id')
->get();
I think there is a minor problem on your expected result(id and name is not matching) but i made it work as following;
The query;
SELECT scores.*, skills.*
FROM scores
INNER JOIN (SELECT skill_id, max(id) AS maxId
FROM scores
WHERE player_id = 1
GROUP BY skill_id) AS sub ON sub.maxId = scores.id
INNER JOIN skills ON skills.id = scores.skill_id;
The eloquent version (You may replace it with DB::table() if you want)
$subQuery = Score::where('player_id', DB::raw($this->id))
->groupBy('skill_id')
->select('skill_id', DB::raw('MAX(id) as maxId'));
return Score::join(DB::raw('(' . $subQuery->toSql() . ') as subQuery'), 'subQuery.maxId', '=', 'scores.id')
->join('skills', 'skills.id', '=', 'scores.skill_id')
->get(['scores.*', 'skills.*']);

How to select values from two different tables in SQL

I have two tables in my SQL Server database. The first is catgeories and second is products. There is a column categories_id in both tables.
HERE IS MY TABLE FOR CATEGORIES :
+----+----------+----------+
| id | category | parent |
+----+----------+----------+
| 1 | BOY | 0 |
| 2 | GIRL | 0 |
| 3 | SHIRT | 1 |
| 4 | SKIRT | 2 |
| 5 | JACKET | 1 |
+----+----------+----------+
TABLE : PRODUCTS
+-------+--------------+----------------------+
| id | title |PRICE | Categories |
+-------+--------------+------+---------------+
| 1 | RED SHIRT | 300 | 3 |
| 2 | blue SKIRT | 500 | 4 |
| 3 | jeans jacket | 500 | 3 |
+-------+--------------+------+-----+---------+
Now I want to select the values from Products table for a particular category like BOY.
Try This:
SELECT pr.id,pr.title,pr.price from products AS pr
INNER JOIN CATEGORIES AS cat ON cat.id=pr.Categories
WHERE cat.category='Boy';
SELECT products.* FROM products INNER JOIN categories ON products.categories = categories.id WHERE categories.category LIKE '%BOY%';
Use this query..
Either
SELECT * FROM tproducts WHERE categories = 1
or
SELECT * FROM tproducts
JOIN tcategories ON tcategories.id = tproducts.categories WHERE tcategories.category = 'BOY'
I don't know your table names so I just used tproducts and tcategories
There is no boy(1) ID in Categories(field) in PRODUCTS(table)
SELECT * FROM CATEGORIES
INNER JOIN PRODUCTS
ON CATEGORIES.id=PRODUCTS.Categories
WHERE CATEGORIES.category ='BOY'
FOR this use join query Example:
select *(or you can get any column as you write name) from table1 join table2 on table1.id=table2.id where table1.category='BOY';

Select foreign key (group) where is the biggest match

I have three tables group_sentences, group_sentences_attributes and group_senteces_categories.
I have an attributes array which I am using in query with IN (after implode).
Then I have one category ID because they are stored recursively, so no need for an array.
I need to select one group number where is the biggest match for $attributesArray and of course category too.
Here is table group_sentences_attributes
+-----+-------+-----------+
| id | group | attribute |
+-----+-------+-----------+
| 1 | 1 | 3564 |
| 2 | 1 | 3687 |
| 3 | 1 | 3689 |
| 4 | 2 | 3687 |
| 5 | 2 | 3564 |
+-----+-------+-----------+
Here is group_sentences_category
+-----+-------+----------+
| id | group | category |
+-----+-------+----------+
| 1 | 1 | 1564 |
| 2 | 1 | 1221 |
| 3 | 1 | 1756 |
| 4 | 2 | 1358 |
| 5 | 2 | 1125 |
+-----+-------+----------+
Here is my query, but I am afraid that it won't do the job done.
SELECT group_categories.group
FROM group_categories, group_attributes
WHERE group_categories.category = '$category'
AND group_attributes.attribute IN ($attributesArray)
GROUP BY group_categories.group
ORDER BY count(group_attributes.attribute)
Any help would be appreciated, thanks.
First, the table in your query do not match the tables in the question. I am guessing they are simply missing the "sentence". Then, you have no join clause. Simple rule: Never use commas in the from clause.
group is a lousy name for a column, because it is a keyword in SQL. The following may be what you are looking for:
SELECT gc.groupid
FROM group_sentences_attributes sa JOIN
group_sentences_category sc
ON sa.groupid = sc.groupid
WHERE sc.category = '$category' AND
sa.attribute IN ($attributesArray)
GROUP BY sa.groupid
ORDER BY count(sa.attribute);
If you only want one row, then add LIMIT 1 to the end.

Left join in codeigniter

I have 3 tables,
itemmaster
|--------|----------|
| id | name |
|--------|----------|
| 1 | Pizza |
|--------|----------|
| 2 | Burger |
|--------|----------|
| 3 | Pepsi |
---------------------
order
|--------|----------|
|orderid | date |
|--------|----------|
| 1 | 1-1-11 |
|--------|----------|
| 2 | 2-1-11 |
|--------|----------|
| 3 | 3-1-11 |
---------------------
orderdetails
|--------|-------------|---------|---------|
| id | orderid |itemid |quantity |
|--------|-------------|---------|---------|
| 1 | 1 | 1 | 10 |
|--------|-------------|---------|---------|
| 2 | 1 | 2 | 20 |
|--------|-------------|---------|---------|
| 3 | 2 | 1 | 10 |
-------------------------------------------
I want to join these 3 tables to get quantity of items of an order that placed on a particular date.
What I have tried is
$this->db->from('itemmaster');
$this->db->join('orderdetails', 'orderdetails.itemid= itemmaster.id','left');
$this->db->join('order', 'order.orderid= orderdetails.orderid');
$this->db->where('order.date',"1-1-11");
$query = $this->db->get();
I got Result as,
Pizza------ 10
Burger------10
What I want is,
Pizza-------10
Burger------20
Pepsi-------0
If changing the all the joins to left joins, you can always do it in two separate query and do a union between the two of them. One would get all the lines that actualy have a quantity and the other would get the rests and put them toguether.
It would look a bit like this. there might be some synthax error, but you'll have to rewrite it in php anyway:
p.s. to add up the quantities, you can use sum()
Select itemmaster.name, orderdetails.quantity from itemmaster
left join orderdetails on orderdetails.itemid = itemmaster.id
left join order on order.orderid = orderdetails.orderid
where order.date = '1-1-11'
group by itemmaster.name
Union
Select itemmaster.name, '0' as quantity From itemmaster
except (Select itemmaster.name, orderdetails.quantity from itemmaster
left join orderdetails on orderdetails.itemid = itemmaster.id
left join order on order.orderid = orderdetails.orderid
where order.date = '1-1-11'
group by itemmaster.name)
group by itemmaster.name
hope this helps ! good luck

Select records without category in many to many relationship

I have a db with some products, they can be "tagged" with many categories. Some products have not an assigned category and I need to find them. Ineed to find records without category. I have created this tables:
ITEMS
+----+------+
| ID | Item |
+----+------+
| 1 | qwe |
| 2 | asw |
| 3 | wgr |
+----+------+
CATEGORIES
+----+----------+
| ID | Category |
+----+----------+
| 1 | xxx |
| 2 | yyy |
+----+----------+
RELATIONSHIP
+---------+--------+
| id_item | id_cat |
+---------+--------+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
+---------+--------+
This is the (not working) query:
SELECT item.id COUNT(relationship.id_item) AS n
FROM item
JOIN relationships GROUP
BY relationships .n
WHERE item.id = relationships.id_item
AND relationships.n =0;
you can use subquery with NOT IN clause
SELECT i.id
FROM item i
WHERE i.id NOT IN ( SELECT r.id_item
FROM RELATIONSHIP r);
You want a left join and then find the ones that don't match:
SELECT i.id, COUNT(relationship.id_item) AS n
FROM item i LEFT OUTER JOIN
relationships r
on i.id = r.id_item
WHERE r.id_item is null;

Categories