CodeIgniter Self-Join doesn't match SQL - php

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

Related

Display 0 results in the left join query

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

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

Join Three tables in mysql with weird requirement

I have three tables in my db.
Table A has the fields
KEYID | KeyName
27 | Income
28 | Account Number
Table B has the fields
UserID | Email | Name | Phone
481 | test#gmail.com | test | 99999999
Table C has the fields
ID | KEYID | UserID | Value
1 | 27 | 481 | 10,000
I need to display the table fields headers are:
UserID | Email | Name | Phone | Income
and the table values should be like this:
481 | test#gmail.com | test | 99999999 | 10,000
I can get the KeyIDs which should be displayed in the table. In this example the KeyIDs string is '27' . I tried with joining and i can fetch & display the value in the table. but i dont know how i can show the key name as table header.
Any Idea.?
You can use a pair of inner join
select b.UserID, b.Email , b.Name, c.value as income
from tableB as b inner join tableC as C on b.userID = c.userId
inner join tableA as a on a.keyID = c.keyID
and a.keyname = 'Income';
and the query you provided in comment
select
b.UserID
, b.Email
, b.Name
, Group_Concat(Distinct Concat(c.keyID,’^:^’,c.value)
Order By c.id Separator ‘;’) As Keyvalues
from tableB as b
inner join tableC as C on b.userID = c.userId
inner join tableA as a on a.keyID = c.keyID;
and with CASE should be
select
b.UserID
, b.Email
, b.Name
, Group_Concat(Distinct CASE
WHEN c.keyID IN ('1,23,10') THEN Concat(c.keyID,’^:^’,c.value) END
Order By c.id Separator ‘;’) As Keyvalues
from tableB as b
inner join tableC as C on b.userID = c.userId
inner join tableA as a on a.keyID = c.keyID;
This query should help to get your desire result.
select b.UserID, b.Email, b.Name, b.Phone, c.Value as Income
from table_b as b
JOIN table_c as c ON (b.UserID = c.UserID)
where c.KEYID = 27
Try this:
SELECT b.userid, b.email, b.name, b.phone, c.value as income
FROM a
LEFT JOIN c on c.keyid = a.keyid
LEFT JOIN b ob b.userid = c.userid

How to join this 5 tables in mysql?

I have 5 tables that I need to connect to get the necessary data.
Table1
id | number
1 | 1
2 | 5
Table 2
id | number | user_id
1 | 1 | 9
2 | 5 | 8
Table 3
id | name |
8 | john |
9 | jane |
Table 4
id | email
6 | johndoe#example.com
Table 5
id | table4_id | table3_id
1 | 6 | 8
Table 1 is my main table and I want to add the name and email from table 3 and 4 respectively to my select query of table 1, but in order to do so, I would need to use table 2 and 5 to connect them as there is no direct relationship between table 1 and table 3 and 4. I only know how to join 3 tables and not 5 tables and it seems confusing to me on how to proceed with this.
I followed the link here to join Table 1,2 and 3. But I don't know how to proceed with table 4 and 5.
This is the query I tried:
SELECT table1.number, table2.number, table2.user_id, table3.id, table3.name,
table4.id, table4.email, table5.table4_id, table3_id
FROM table1
LEFT JOIN table2
INNER JOIN table3
//this query will work if I don't include this 2 inner joins
INNER JOIN table4
INNER JOIN table5
ON table3.id = table5.table3_id
ON table5.table4_id = table4.id
//
ON table2.user_id= table3.id
ON table2.number = table1.number;
ERROR: (if included the inner join for table 4 and 5)
Error Code: 1064. You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'ON table2.user_id= table3.id
The right Syntax is select .. from .. join .. on .. join ..on ....
SELECT table1.number, table2.number, table2.user_id, table3.id, table3.name, table4.id, table4.email, table5.table4_id, table3_id
FROM table1
LEFT JOIN table2 ON table2.number = table1.number
INNER JOIN table3 ON table2.user_id= table3.id
INNER JOIN table5 ON table3.id = table5.table3_id
INNER JOIN table4 ON table5.table4_id = table4.id
Try with the below structure. I made it from the structure you given in question
select t1.number, t2.number, t2.user_id, t3.id, t3.name,t4.id, t4.email, t5.t4_id, t3_id
from table5 as t5
join table4 as t4 on t5.table4_id = t4.id
join table3 as t3 on t5.table3_id=t3.id
join table2 as t2 on t2.user_id = t3.id
join table1 as t1 on t2.number=t1.number
Try Below code. Hope this will work.
Select t3.name,t4.email,t1.number,t2.user_id
from table3 t3 JOIN table5 t5 ON t3.id=t5.table3_id
JOIN table4 t4 ON t4.id=t5.table4_id
JOIN table2 t2 ON t2.user_id=t3.id
JOIN table1 t1 ON t1.number=t2.number;

3 tables, left join, in case DATA is missing in ONE table

table1 (ids always exist)
+----+------+
| id | col1 |
+----+------+
| 1 | ab |
+----+------+
| 2 | gh |
+----+------+
table2 (ids always exist)
+----+------+
| id | col2 |
+----+------+
| 1 | cd |
+----+------+
| 2 | ij |
+----+------+
table3 (ids might be missing, in this case 2 is missing)
+----+------+
| id | col3 |
+----+------+
| 1 | ef |
+----+------+
PHP
$col = 'ab';
$a = mysql_query("SELECT t1.id FROM table1 AS t1, table2 AS t2, table3 AS t3
WHERE t1.id = t2.id AND t2.id = t3.id AND (t1.col1 = '$col' OR t2.col2 = '$col'
OR t3.col3 = '$col) GROUP BY t1.id, t2.id, t3.id");
That would only work if all three tables had "the same id" included, but what happens if an "id" is missing in table3 for whatever reason? how can I still test for all three tables and get t1.id to output 1, when $col = ab? would I have to use left join?
$a = mysql_query("SELECT t1.id FROM table1 AS t1, table2 AS t2
LEFT JOIN (SELECT id FROM table3 WHERE col3 = '$col') AS t3 ON t3.id = t1.id
WHERE t1.id = t2.id AND (t1.col1 = '$col' OR t2.col2 = '$col')
GROUP BY t1.id, t2.id");
what am I doing wrong here?
What are you doing wrong? Querying a table that doesn't exist. That's always going to raise an error.
I'm not going to address the wisdom of designing a database in which tables crucial to your queries come and go.
Your only hope on the client side is to
test for the existence of the tables
you're interested in, and
execute different SQL statements
based on those results.
[After your edit]
It sounds like you need either one or two left outer joins. This gives you all the ids that are common to both table1 and table2, regardless of whether they're in table3.
select t1.id, t2.id, t3.id
from table1 t1
inner join table2 t2 on (t1.id = t2.id)
left join table3 t3 on (t1.id = t3.id);
And this gives you all the ids that are in table1, regardless of whether they're in table2 or table 3.
select t1.id, t2.id, t3.id
from table1 t1
left join table2 t2 on (t1.id = t2.id)
left join table3 t3 on (t1.id = t3.id);
And, of course, you can filter the results with your WHERE clause.
LEFT JOIN only works when the table DOES exist, but contains no data.
If you don't want to have to do stuff like Catcall suggested (check if the table exists, and use different SQL statements based on that...) you have to make sure that the table exists in the database, even if it's completely empty.
Under normal circumstances, you should have a certain degree of control over your application's database, so you should be able to make sure that the table is really there.
If this is really a big problem (like, that you can't be sure if someone deleted the table) you could check this every time you start your application: create the table if it doesn't exist.

Categories