I am doing a JOIN operation between a table and itself. The table schema is something like:
| id | name | parent |
| 0 | .... | ... |
| 1 | .... | ... |
| 2 | .... | ... |
The query looks like:
$qMarks = str_repeat('?,', count($arr) - 1) . '?';
$stmt = $db->prepare("SELECT t1.id AS t1id, t1.name AS t1name, t2.name AS t2name
FROM cats t1
JOIN cats t2 ON t1.parent = t2.id
WHERE t1.name IN ($qMarks)");
$stmt->execute($arr);
$result = $stmt->fetchAll();
So, I'm passing in an array of names $arr, and I am getting back the rows where there is a matching name to one of the items in the parameter array. This works fine, so long as there is also a matching id somewhere for parent.
But, sometimes the value for parent will be blank (empty cell). I still want to get those results, as long as the t1.name IN ($qMarks) condition is met.
How do I return the values, even if the t1.parent value in the table is blank?
Use a left join.
$stmt = $db->prepare("SELECT t1.id AS t1id, t1.name AS t1name, t2.name AS t2name
FROM cats t1
LEFT JOIN cats t2 ON t1.parent = t2.id
WHERE t1.name IN ($qMarks)");
Related
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
Hello! I need help i have table that has this value
Table1
sorter | valuedata | status | useraccounts |
----------------------------------------------
same | value1 | Disabled | user1 |
same | value2 | Active | user1 |
And
Table2
name | useraccounts |
-------------------------
user1 | displayname1 |
and I wanted to display all the data even they have different status while they are innerjoin like this
SELECT table1.name,table2.useraccounts
FROM table1 INNER JOIN table2 ON table1.useraccounts = table2.name
WHERE table1.sorter = "same" AND table1.status = "Disabled" AND table1.status != "Disabled"
is this even possible to do??
I think you made 2 mistakes:
table 1 does not have name column
what you are look for is an OR instead of AND.
The next is what I think you are looking for:
SELECT table2.[name],table2.useraccounts
FROM table1 INNER JOIN table2 ON table1.useraccounts = table2.name
WHERE table1.sorter = 'same' AND
(table1.status = 'Disabled' OR table1.status != 'Disabled')
and this can be rewritten to the next since checking for 'Disabled' or != 'Disabled' is ALL ROWS.
SELECT table2.[name],table2.useraccounts
FROM table1 INNER JOIN table2 ON table1.useraccounts = table2.name
WHERE table1.sorter = 'same'
Actually, you need the cross join. You can write it without using the JOIN as well:
SELECT table2.name,table2.useraccounts
FROM table1,table2 WHERE table1.useraccounts = table2.name
AND table1.sorter = "same"
SELECT table2.name,table1.useraccounts
FROM table1 INNER JOIN table2 ON table1.useraccounts = table2.name
U will get all data while status is differnt or not
I have the following tables:
posts
---------------------
id | name
---------------------
1 | First Post
2 | Another post
tags
---------------------
id | name
---------------------
1 | Tag1
2 | Tag2
3 | Tag3
posts_tags
---------------------
post_id | tag_id
---------------------
1 | 2
1 | 3
2 | 1
3 | 2
I'm trying to write a query that (in human readable terms) would say something like 'Find all of the posts which are tagged with tag1 or tag2'.
So I can put multiple tag IDs in and get a lists of posts that have at least one of those tags back.
I've tried this:
SElECT t1.name
FROM posts AS t1 INNER JOIN posts_tags AS t2
ON t1.id = t2.post_id
WHERE t2.tag_id IN(1,2)
But this returns no results. I'm not really sure where to go from here. Is there any way I can do this in one query - i.e without first fetching the posts, then looping through them to fetch the tags?
Use the IN operator:
SELECT post_id
FROM posts_tags
WHERE tag_id IN (1,2,3)
To avoid getting post_id duplicates use the DISTINCT:
SELECT DISTINCT post_id
...
SELECT
t1.post_id
FROM
posts_tags as t1
INNER JOIN
posts AS t2
ON
t1.post_id = t2.id
WHERE
t2.tag_id IN(1,2)
By Joining the Posts table you now have access to all of the post data, which I assume is what you are looking for.
you have to join posts_tags table also.
SElECT t1.name FROM posts as t1 INNER JOIN posts_tags as t3 on t3.post_id = t1.id INNER JOIN tags AS t2 ON t2.id = t3.tag_id WHERE t2.id IN(1,2)
SQLFiddle answer here.
http://www.sqlfiddle.com/#!2/d785e/5
SELECT posts.name FROM posts LEFT JOIN post_tags ON posts.id = post_tags.post_id WHERE post_tags.tag_id = '1' OR post_tags.tag_id = '2'
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');
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.