Display 0 results in the left join query - php

How do I count the number of participants in the event_participants table and display also the event_title with zero results. This is my table
event_title
id | name
1 | New York
2 | Canada
event_participants
id | event_title_id | name
1 | 1 | Jon
2 | 1 | Mike
This is my query
SELECT count( * ) AS count
FROM event_participants AS t1
LEFT JOIN event_title AS t2 ON t1.event_title_id = t2.id
GROUP BY t1.event_title_id
I am getting a correct result but does not display the 0 results.
I should be getting a result like this
New York | 2
Canada | 0

In place of * use t2.id it will work
SELECT count(t2.id) AS count
FROM event_participants AS t1
LEFT JOIN event_title AS t2 ON t1.event_title_id = t2.id
GROUP BY t1.event_title_id

Your group by is the problem.
you are grouping by the event_title_id where you dont have the id 2.
What you should do is a group by the name of the first table.
SELECT count( * ) AS count
FROM event_participants AS t1
LEFT JOIN event_title AS t2 ON t1.event_title_id = t2.id
GROUP BY t2.name
should work

Change your query like below to get desired output:
SELECT count(t2.id) AS count
FROM event_title AS t1
LEFT JOIN event_participants AS t2 ON t2.event_title_id = t1.id
GROUP BY t1.id
//To retrieve title also
SELECT t1.title,count(t2.id) AS count
FROM event_title AS t1
LEFT JOIN event_participants AS t2 ON t2.event_title_id = t1.id
GROUP BY t1.id

Related

get number of rows in join query

I am saving Item and order in different tables. i want to count order as per item.
Here is my table structure.
Table1: Order table
id | table2_id
1 | 1
2 | 1
3 | 2
4 | 2
Table2: Item Table
id | user_id
1 | 1
2 | 2
3 | 1
4 | 2
One item has multiple order as shown in the table structure. Now i want to count the order as each item.
I have tried using join but it gives me all row cont: 4
SELECT count(Table1.id) as order_count_for_each_item
FROM `Table2` as `t2`
LEFT OUTER JOIN `Table1` as `t2` ON `t1`.`id` = `t2`.`table2_id`;
But i want each item count: as For Item1 is: 2 and Item2 is: 2
The conclusion:
As Rahul Suggested this:
SELECT count(*) as order_count_for_each_item
FROM `Table2` as t2
LEFT OUTER JOIN `Table1` as t1 ON `t1`.`table2_id` = `t2`.id
GROUP BY t1.`table2_id`
This query give the me result which i want initially.
order_count_for_each_item
1 |
2 |
But the answer i accepted (Bibhudatta Sahoo) gives me the item count which is zero and also the count of item par order.
SELECT t2.`id`,
(SELECT count(t1.id) form `Table1` as t1
where t2.`id` = t1.`table2_id`) as order_count_for_each_item
FROM `Table2` as t2
group by t2.`id`
order by t2.`id` asc
Item ID | order_count_for_each_item
1 | 2
2 | 2
3 | 0
4 | 0
So I accepted that answer.
Try Like this
SELECT t2.`id`,
(SELECT count(t1.id) form `Table1` as t1
where t2.`id` = t1.`table2_id`) as order_count_for_each_item
FROM `Table2` as t2
group by t2.`id`
order by t2.`id` asc
You are missing a group by here
SELECT count(*) as order_count_for_each_item
FROM `Table2` as t2
LEFT OUTER JOIN `Table1` as t1 ON `t1`.`table2_id` = `t2`.id
GROUP BY t1.`table2_id`
You will have to use an aggregate function Group by. group your data over the item and get the count.
SELECT item.id,ifnull(count(order.id),0) as order_count_for_each_item
FROM `Table2` as `item`
LEFT JOIN `Table1` as `order` ON order.table2_id=item.id
group by item.id ;

how to get data from both table with join

Table 1 : Main_Family_Member
ID | Name
1 | Mahesh
2 | Rahul
3 | Jay
Table 2 : Family_Members
ID | MainMember | Name
1 | 1 | 'Arun'
2 | 1 | 'Nitin'
3 | 2 | 'Pratik'
Want Result :
Name
Mahesh
Arun
Nitin
Rahul
Pratik
You can achieve this by doing a UNION ALL of the two tables along with proper ordering. Note that it is necessary to union the two tables joined, because we need to know whether a main family member has any members. In case he does not have any member, your sample output implies that you don't want to display that main family member at all.
SELECT t.Name
FROM
(
SELECT DISTINCT t1.ID, t1.Name, 0 AS position
FROM
(
SELECT t1.ID, t1.Name
FROM Main_Family_Member t1
INNER JOIN Family_Members t2
ON t1.ID = t2.MainMember
WHERE t2.ID IS NOT NULL
) t1
UNION ALL
SELECT t2.ID, t2.Name, 1 AS position
FROM
(
SELECT t2.MainMember AS ID, t2.Name
FROM Main_Family_Member t1
INNER JOIN Family_Members t2
ON t1.ID = t2.MainMember
WHERE t2.ID IS NOT NULL
) t2
ORDER BY ID, position, Name
) t
Demo here:
SQLFiddle
SELECT Main_Family_Member.Name, Family_Members.Name
FROM Main_Family_Member
INNER JOIN Family_Members
ON Main_Family_Member.ID = Main_Family_Member.MainMember;
SELECT Main_Family_Member.Name, Family_Members.Name
FROM Main_Family_Member
INNER JOIN Family_Members
ON Main_Family_Member.ID = Main_Family_Member.MainMember;
You will need to perform a INNER JOIN on the two tables. This would return all the rows in the first table that meet the conditions plus all rows on the second table that join with the first table on the unique fields.
SELECT Main_Family_Member.Name , Family_Members.Name FROM Main_Family_Member INNER JOIN Family_Members ON Main_Family_Member.ID = Family_Members.MainMember WHERE Main_Family_Member.ID = 1 OR Main_Family_Member.ID = 2
SELECT Main_Family_Member.Name,Family_Members.Name FROM Main_Family_Member
INNER JOIN Family_Members ON Main_Family_Member.ID=Family_Members.MainMember

Get results by count and operators in one query

I think question is wrong, but i don't know how to ask properly.
This query selects all businesses with all workers, whose job_types contains C letter.
$connect = DB::table('relationship')
->join('workers', 'workers.id', '=', 'relationship.w_id')
->join('business', 'business.id', '=', 'relationship.b_id')
->whereRaw('job_types LIKE "%C%"')
->groupBy('relationship.w_id')
->get();
I am using foreach for displaying results
foreach ($connect as $item) {
echo $item->name;
// etc
}
I want to select all businesses who have more than 3 or less than 3 or equal to 3 (depends of what i need) job_types LIKE "%C%" and store information like that:
1. APPLE | Tom | C
2. APPLE | Tim | C
3. APPLE | Jeff | C
4. IBM | Jenny | C
5. IBM | Sean | C
6. IBM | Ian | C
// etc``
Answer by #KikiTheOne is kinda working, but it does not display results as needed.
*****SOLUTION*****
SELECT
*
FROM
people_details as t1
inner join
people_branches as t2
on t1.id = t2.id
inner join
(
SELECT
count(t1.id) as worker_counter,t1.branch_id
FROM
people_branches as t1
inner join people_details as t2
on t1.id = t2.id
WHERE
t2.job_types LIKE '%C%'
group by branch_id
) as t3
on t2.branch_id = t3.branch_id
inner join people_frontpage as t4
on t4.id = t1.id
inner join business as t5
on t5.id = t2.branch_id
WHERE
t1.job_types LIKE '%C%'
AND t3.worker_counter > 200
----------
OLD - UPDATE
SELECT
t3.bus_name, t1.name, t1.job_types
FROM
SO_WORKER as t1
inner join
SO_RELATIONSHIP as t2
on t1.id = t2.w_id
inner join
(
SELECT
count(t1.w_id) as worker_counter,t1.b_id,t3.bus_name
FROM
SO_RELATIONSHIP as t1
inner join SO_WORKER as t2
on t1.w_id = t2.id
inner join SO_BUSINESS as t3
on t3.id = t1.b_id
WHERE
t2.job_types LIKE '%C%'
group by b_id
) as t3
on t2.b_id = t3.b_id
WHERE t1.job_types LIKE '%C%'
AND t3.worker_counter <= 3
Unformated
SELECT t3.bus_name, t1.name, t1.job_types FROM SO_WORKER as t1 inner join SO_RELATIONSHIP as t2 on t1.id = t2.w_id inner join (SELECT count(t1.w_id) as worker_counter,t1.b_id,t3.bus_name FROM SO_RELATIONSHIP as t1 inner join SO_WORKER as t2 on t1.w_id = t2.id inner join SO_BUSINESS as t3 on t3.id = t1.b_id WHERE t2.job_types LIKE '%C%' group by b_id) as t3 on t2.b_id = t3.b_id WHERE t1.job_types LIKE '%C%' AND t3.worker_counter <= 3
--------------------------------------------------
OLD CODE
in Relation to the comments from Post 1.
Table: SO_BUSINESS
id | bus_name
--------------------
1 | BUSI A
2 | BUSI B
Table: SO_WORKER
id | job_types
---------------------
1 | CEO
2 | GFO
3 | CTO
4 | Manager
5 | Worker
Table: SO_RELATIONSHIP
w_id | b_id
----------------
1 | 1
2 | 2
3 | 1
4 | 1
5 | 2
Query: Output
workers_count | b_id | bus_name
--------------------------------------------
2 | 1 | BUSI A
.
SELECT *
FROM
(
SELECT
count(t1.w_id) as workers_count,
t1.b_id,
t3.bus_name
FROM
SO_RELATIONSHIP as t1
inner join
SO_WORKER as t2 on t1.w_id = t2.id
inner join
SO_BUSINESS as t3 on t1.b_id = t3.id
WHERE
t2.job_types LIKE '%C%'
GROUP BY t1.b_id
) as t4
WHERE
t4.workers_count < 3
Code unformated:
SELECT * FROM (SELECT count(t1.w_id) as workers_count,t1.b_id,t3.bus_name FROM SO_RELATIONSHIP as t1 inner join SO_WORKER as t2 on t1.w_id = t2.id inner join SO_BUSINESS as t3 on t1.b_id = t3.id WHERE t2.job_types LIKE '%C%' GROUP BY t1.b_id) as t4 WHERE t4.workers_count < 3
Let me know if this helps u
$connect = DB::table('relationship')
->join('workers', 'workers.id', '=', 'relationship.w_id')
->join('business', 'business.id', '=', 'relationship.b_id')
->selectRaw('workers.*,business.*,(select count(*) from workers where job_types like "%c%") as workers_count')
->where('job_types', 'like', '%C%')
->having('workers_count','>=',5)
->groupBy('relationship.w_id')
->get();

CodeIgniter Self-Join doesn't match SQL

Alright, have to be missing something here.
My SQL works fine:
SELECT t1.id, t1.material, t2.id, t2.material, t3.id, t3.material, t4.id, t4.material
FROM ml_levels t1
LEFT JOIN ml_levels t2
ON t1.parentID = t2.id
LEFT JOIN ml_levels t3
ON t2.parentID = t3.id
LEFT JOIN ml_levels t4
ON t3.parentID = t4.id
WHERE t1.id = 286
This returns
id | material | id | material | id | material | id | material
-------------------------------------------------------------------------------------------
286 | 4Layer | 209 | Protective Film | 60 | Specialty Products | 1 | Protect
However, my ActiveRecord is only returning t4.id and t4.material:
$this->db->select('t1.id, t1.material, t2.id, t2.material, t3.id, t3.material, t4.id, t4.material');
$this->db->from('ml_levels AS t1')->where('t1.id',286);
$this->db->join('ml_levels AS t2','t1.parentID = t2.id','left');
$this->db->join('ml_levels AS t3','t2.parentID = t3.id','left');
$this->db->join('ml_levels AS t4','t3.parentID = t4.id','left');
return $this->db->get()->row();
this returns:
id | material |
-------------------
1 | Protect |
$this->db->last_query() returns:
SELECT `t1`.`id`, `t1`.`material`, `t2`.`id`, `t2`.`material`, `t3`.`id`, `t3`.`material`, `t4`.`id`, `t4`.`material`
FROM (`ml_levels` AS t1)
LEFT JOIN `ml_levels` AS t2 ON `t1`.`parentID` = `t2`.`id`
LEFT JOIN `ml_levels` AS t3 ON `t2`.`parentID` = `t3`.`id`
LEFT JOIN `ml_levels` AS t4 ON `t3`.`parentID` = `t4`.`id`
WHERE `t1`.`id` = 286
And if I run this SQL on the database, it returns exactly what the original query returned.
Codeigniter return only field name without table label so that you found only two fields because there are only id and material. Change line:
$this->db->select('t1.id, t1.material, t2.id, t2.material, t3.id, t3.material, t4.id, t4.material');
with:
$this->db->select('t1.id AS t1id, t1.material AS t1material, t2.id AS t2id, t2.material AS t2material, t3.id AS t3id, t3.material AS t3material, t4.id AS t4id, t4.material AS t4material');

SELECT biggest row from a LEFT JOIN

I have a SQL query that LEFT JOINs a table into it. This causes rows from the main table to be duplicated but with different rows from the JOINed table. How do I only select the rows with the highest date from the JOINed table.
Here's an example (this is the result from my query):
ID Message Date
---------------------------
0 Hi 2011-01-01
0 Bye 2011-02-05
0 Hello 2011-04-20
1 Test 2010-12-31
1 Testing 2010-11-15
2 Something 2010-12-12
2 Nothing 2011-01-01
2 Yes 2010-02-05
3 Cool NULL
I want one row per ID, the row with the highest ID.
ID Message Date
---------------------------
0 Hello 2011-04-20
1 Test 2010-12-31
2 Nothing 2011-01-01
3 Cool NULL
My current query is something like this (I just kinda made this up, but it's similar to the real one):
SELECT t1.ID, t2.Message, t2.Date
FROM t1
LEFT JOIN (
SELECT t3.ID, t3.message, t3.Date
FROM t3
LEFT JOIN t4 ON t4.userID = 12 AND t3.ID = t4.ID
WHERE t4.color = 'blue'
) AS t2
ON t1.ID = t2.ID
WHERE t1.userID = 12
I guess I could use PHP and loop through the results and pick out the ones I want, but can I have MySQL do that for me?
EDIT: Sorry, my 1st example was way wrong, this is more like what I want.
EDIT 2: I tried using GROUP BY and MAX, but I think I'm doing something wrong.
I tried:
SELECT t1.ID, t2.Message, MAX(t2.Date)
FROM t1
LEFT JOIN (
SELECT t3.ID, t3.message, t3.Date
FROM t3
LEFT JOIN t4 ON t4.userID = 12 AND t3.ID = t4.ID
WHERE t4.color = 'blue'
) AS t2
ON t1.ID = t2.ID
WHERE t1.userID = 12
GROUP BY t1.ID
But, that gave me:
ID Message Date
---------------------------
0 Hi 2011-04-20
1 Test 2010-12-31
2 Something 2011-01-01
3 Cool NULL
How do I get the Message associated with the highest date.
Select t1.id, t1.Message, t3.date
From t1
Left Join t3
On t3.id = t1.id
And t3.id = (
Select Max( t3_1.Id )
From t3 As t3_1
Where t3_1.id = t3.id
Having Max( t3_1.date ) = t3.date
)
Where t1.userID = 12
As far as I can tell, the join to t4 plays no part in the query whatsoever. It doesn't filter the results nor is anything from the t4 table displayed in the Select clause. In addition, I have assumed that the column t3.id is actually a foreign key to the t1 table and not the primary key. If it is the primary key, then the other filter for max date is not necessary.
Update given question revision
By adding criteria to the Where clause on t4, you have effectively converted it to an inner join. Still, one solution is:
Select t1.id, t3.Message, t3.date
From t1
Left Join t3
On t3.id = t1.id
And t3.id = (
Select Max( t3_1.Id )
From t3 As t3_1
Join t4
On t4.id = t3_1.id
Where t4.color = 'blue'
And t3_1.id = t3.id
Having Max( t3_1.date ) = t3.date
)
Where t1.userID = 12
Like this:
SELECT
t1.ID,
t1.Message,
MAX(t2.Date) as [Date]
FROM t1
LEFT JOIN (
SELECT t3.ID, t3.Date
FROM t3
LEFT JOIN t4 ON t4.userID = 12 AND t3.ID = t4.ID
WHERE t3.color = 'blue'
) AS t2
ON t1.ID = t2.ID
WHERE t1.userID = 12
GROUP BY t1.ID, t1.Message
You can use GROUP BY to group on certain values with the restriction that you have to group on all the values in the select list, unless it is an aggregate function, like MAX.

Categories