I have 2 tables orders and customers with data as:
mysql> select * from orders;
+---------+----------------+----------+-------+
| orderid | product | customer | price |
+---------+----------------+----------+-------+
| 292 | sofa | 101 | 6000 |
| 293 | table | 105 | 3000 |
| 294 | table | 104 | 1450 |
| 295 | table | 101 | 1200 |
| 296 | chair | 103 | 800 |
| 297 | dressing table | 104 | 9000 |
| 298 | corner | 102 | 1000 |
| 299 | corner | 102 | 900 |
| 300 | bed | NULL | NULL |
| 301 | door | NULL | NULL |
+---------+----------------+----------+-------+
10 rows in set (0.00 sec)
mysql> select * from customers;
+--------+----------+-----------+
| custid | name | location |
+--------+----------+-----------+
| 101 | jaspreet | New delhi |
| 102 | harpreet | Jalandhr |
| 103 | surjit | Amritsar |
| 104 | harneet | ludhiana |
| 105 | hashar | New Delhi |
| 106 | harneet | NULL |
+--------+----------+-----------+
6 rows in set (0.00 sec)
When i run inner join, it return the following data:
mysql> select orders.orderid,customers.name from orders inner join customers where orders.customer=customers.custid;
+---------+----------+
| orderid | name |
+---------+----------+
| 292 | jaspreet |
| 295 | jaspreet |
| 298 | harpreet |
| 299 | harpreet |
| 296 | surjit |
| 294 | harneet |
| 297 | harneet |
| 293 | hashar |
+---------+----------+
8 rows in set (0.00 sec)
But the outer joins are not working on this.
mysql> select orders.orderid,customers.name from orders left join customers where orders.customer=customers.custid;
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use n ear 'where orders.customer=customers.custid' at line 1
Can someone help me with this concept?
Thanks in advance
You're looking for ON not WHERE:
SELECT orders.orderid,
customers.name
FROM orders
LEFT JOIN customers
ON orders.customer = customers.custid;
The JOIN condition is specified with ON, not WHERE:
SELECT orders.orderid,
customers.name
FROM orders
LEFT JOIN customers
ON orders.customer = customers.custid;
You should use this with both inner and outer joins. WHERE should be used for conditions on individual tables, not joining conditions.
You were able to get away without this for the inner join because a join without an ON clause performs a full cross product, and then the WHERE clause filters based on testing across this. I'm not sure why, but you can't do this with outer join.
Related
I read that the output of the subquery doesn't matter and only its existence matter. But, when I change the code in the subquery, why is my output changing?
These are the tables:
mysql> select * from boats;
+------+-----------+-------+
| bid | bname | color |
+------+-----------+-------+
| 101 | Interlake | blue |
| 102 | Interlake | red |
| 103 | Clipper | green |
| 104 | Marine | red |
+------+-----------+-------+
mysql> select * from sailors;
+------+---------+--------+------+
| sid | sname | rating | age |
+------+---------+--------+------+
| 22 | Dustin | 7 | 45 |
| 29 | Brutus | 1 | 33 |
| 31 | Lubber | 8 | 55.5 |
| 32 | Andy | 8 | 25.5 |
| 58 | Rusty | 10 | 35 |
| 64 | Horatio | 7 | 35 |
| 71 | Zorba | 10 | 16 |
| 74 | Horatio | 9 | 40 |
| 85 | Art | 3 | 25.5 |
| 95 | Bob | 3 | 63.5 |
+------+---------+--------+------+
10 rows in set (0.00 sec)
mysql> select * from reserves;
+------+------+------------+
| sid | bid | day |
+------+------+------------+
| 22 | 101 | 1998-10-10 |
| 22 | 102 | 1998-10-10 |
| 22 | 103 | 1998-10-08 |
| 22 | 104 | 1998-10-08 |
| 31 | 102 | 1998-11-10 |
| 31 | 103 | 1998-11-06 |
| 31 | 104 | 1998-11-12 |
| 64 | 101 | 1998-09-05 |
| 64 | 102 | 1998-09-08 |
| 74 | 103 | 1998-09-08 |
+------+------+------------+
select sname from sailors s where exists(select * from reserves r where r.bid=103);
+---------+
| sname |
+---------+
| Dustin |
| Brutus |
| Lubber |
| Andy |
| Rusty |
| Horatio |
| Zorba |
| Horatio |
| Art |
| Bob |
+---------+
10 rows in set (0.00 sec)
mysql> select sname from sailors s where exists(select * from reserves r where r.bid=103 and r.sid=s.sid);
+---------+
| sname |
+---------+
| Dustin |
| Lubber |
| Horatio |
+---------+
Also, I am not able to understand what r.sid=s.sid is doing here. All the sid in reserves are already from sailors table. Please someone explain it to me.
The EXISTS is a Boolean Operator which indicates that if there is ANY row in the sub-query you passed to it. When you execute this:
EXISTS(SELECT * FROM reserves r WHERE r.bid=103)
It will return TRUE after finding the FIRST row which has the condition bid = 103 in Reserves table. The first part of the query doesn't matter, it does not matter what you SELECT in Exists and MySQL engine will ignore it, just the WHERE clause is the part which makes the difference, you can use Exists even like this:
EXISTS(SELECT 1 FROM reserves r WHERE r.bid=103)
In the query above, nothing depends on the values in main query, nothing depends on Sailors table, and if there is ANY row in the Reserves table with bid = 103, then it always will return TRUE.
In the second sub-query with EXISTS, you have a different WHERE clause, and it depend on the value of the fields of the main Query, so it will have different result per each row:
EXISTS(SELECT * FROM reserves r WHERE r.bid=103 AND r.sid=s.sid)
In the above query, per each row in Sailors table, MySQL uses sid value to produce the WHERE condition of the sub-query in EXISTS operator, so it will returns TRUE for a row in Sailors table if there are ANY rows in Reserves table which has a bid = 103 and sid = Sailors.sid, and it will returns False for those that has not such a record in Reserves table, and finally you will get a different result
I think I got that. Exists is used to check if the subquery is existing for the main query. I didn't give any link for the main query and subquery in the first query.
For every name in sailors, independently, the subquery is existing. Hence, I got all the names. In the second query, I added s.sid=r.sid which links the main query and subquery. It checks if for a sname, if bid=103, and also, if s.sid=r.sid.
Please comment if I got that right.
i am watching a tutorial. There is a code which i don't understand what is supposed to do.
$sql = 'SELECT p.*,
a.screen_name AS author_name,
c.name AS category_name
FROM
posts p
LEFT JOIN
admin_users a ON p.author_id = a.id
LEFT JOIN
categories c ON p.category_id = c.id
WHERE
p.id = ?';
I read about the left joins but i didn't understand them. Can somebody please explain me the code i shared.
Thanks in advance!
Imagine you have two tables. One that stores the information about the programmers on your website, and the other table that keeps track of their online purchases.
PROGRAMMERS Table
+--------------------------------------------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Desire | 32 | 123 fake s| 3000.00 |
| 2 | Jamin | 25 | 234 fake s| 2500.00 |
| 3 | Jon | 23 | 567 fake s| 2000.00 |
| 4 | Bob | 30 | 789 fake s| 1500.00 |
| 5 | OtherGuy | 31 | 890 fake s| 1000.00 |
| 6 | DudeMan | 32 | 901 fake s| 500.00 |
+--------------------------------------------+
PURCHASES Table
+---------------------------------------------+
| ORDER_ID | PROG_ID | DATE | PRICE |
+-------------+---------+---------------------|
| 1 | 1 | 1-1-2017 | 100 |
| 2 | 2 | 1-2-2017 | 200 |
| 3 | 6 | 1-3-2017 | 300 |
+---------------------------------------------|
You decide you need to make a new table to consolidate this information to a table that contains
certain columns you want.
For example, you figure it would be nice for shipping purposes to have a table
that has the ID, the NAME, the PRICE, and the DATE columns.
Currently, the tables we have don't display all of that in a single table.
If we were to LEFT JOIN these tables, we would end up filling the desired columns
with NULL values where there is no information to join.
SELECT ID, NAME, PRICE, DATE
FROM PROGRAMMERS
LEFT JOIN PURCHASES
ON PROGRAMMERS.ID = PURCHASES.PROG_ID;
Notice that I'm selecting the columns I want from the starting table, then joining the right table
even though there might be missing information.
RESULTING TABLE
+-------------------------------------+
| ID | NAME | PRICE | DATE |
+----+----------+-----------------+---+
| 1 | Desire | 100 | 1-1-2017 |
| 2 | Jamin | 200 | 1-2-2017 |
| 3 | Jon | NULL | NULL |
| 4 | Bob | NULL | NULL |
| 5 | OtherGuy | NULL | NULL |
| 6 | DudeMan | 300 | 1-3-2017 |
+-------------------------------------+
For a visual representation of the difference between SQL JOINs check out
https://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins .
I have following tables with data as:
1.Table follow_up as :
mysql> select * from follow_up;
+--------------+----------------+--------------------------------------------------+-------------------+---------+---------------+-----------+---------------+----------+
| follow_up_id | feedback_close | feedback_open | is_email_required | is_Open | reminder_date | client_id | conclusion_id | stage_id |
+--------------+----------------+--------------------------------------------------+-------------------+---------+---------------+-----------+---------------+----------+
| 1 | NULL | dsffsdfsdfsd | 1 | 1 | 2017-09-20 | 101 | 96 | 72 |
| 2 | NULL | FSGDFHFGHFG | 1 | 1 | 2017-09-28 | 101 | 251 | 72 |
| 3 | NULL | Tender stage fb | 0 | 1 | NULL | 101 | 98 | 163 |
| 4 | NULL | Call back tender stage update date from 28 to 30 | 1 | 1 | 2017-09-28 | 101 | 96 | 163 |
| 5 | NULL | Metting follow up for next meeting | 1 | 1 | 2017-10-02 | 101 | 96 | 73 |
+--------------+----------------+--------------------------------------------------+-------------------+---------+---------------+-----------+---------------+----------+
2. Table logs as :
mysql> SELECT * from logs where transaction = 'FLWUP';
+---------+---------+---------------------+---------+-------------+
| user_id | menu_id | logs_time | tran_id | transaction |
+---------+---------+---------------------+---------+-------------+
| 84 | 69 | 2017-09-19 19:31:04 | 1 | FLWUP |
| 84 | 69 | 2017-09-19 19:31:25 | 2 | FLWUP |
| 84 | 69 | 2017-09-20 19:10:41 | 2 | FLWUP |
| 84 | 69 | 2017-09-21 12:35:01 | 3 | FLWUP |
| 84 | 69 | 2017-09-21 12:35:26 | 4 | FLWUP |
| 84 | 69 | 2017-09-21 12:36:16 | 4 | FLWUP |
| 84 | 69 | 2017-09-21 12:38:30 | 5 | FLWUP |
+---------+---------+---------------------+---------+-------------+
7 rows in set (0.00 sec)
3. table allcode as :
mysql> select * from allcode where code_type like 'MARK%';
+------------------+---------+------+----------------------+
| code_type | code_id | srno | code_name |
+------------------+---------+------+----------------------+
| MARKETING_STAGES | 72 | 1 | Enquiry |
| MARKETING_STAGES | 73 | 3 | Meeting |
| MARKETING_STAGES | 74 | 4 | Presentation |
| MARKETING_STAGES | 163 | 2 | Tender |
+------------------+---------+------+----------------------+
11 rows in set (0.00 sec)
I have invoked a query and got result as :
mysql> select f.follow_up_id,f.feedback_open, f.feedback_close, f.reminder_date,
ast.code_name as stage, ac.code_name as conclusion, max(l.logs_time)
from follow_up f
join logs l on l.tran_id = f.follow_up_id
join allcode ast on ast.code_id = f.stage_id
join allcode ac on ac.code_id = f.conclusion_id
where l.transaction='FLWUP' and f.client_id = 101
group by ast.code_name order by ast.srno;
+--------------+------------------------------------+----------------+---------------+---------+------------+---------------------+
| follow_up_id | feedback_open | feedback_close | reminder_date | stage | conclusion | max(l.logs_time) |
+--------------+------------------------------------+----------------+---------------+---------+------------+---------------------+
| 1 | dsffsdfsdfsd | NULL | 2017-09-20 | Enquiry | Call Back | 2017-09-20 19:10:41 |
| 3 | Tender stage fb | NULL | NULL | Tender | Next | 2017-09-21 12:36:16 |
| 5 | Metting follow up for next meeting | NULL | 2017-10-02 | Meeting | Call Back | 2017-09-21 12:38:30 |
+--------------+------------------------------------+----------------+---------------+---------+------------+---------------------+
3 rows in set (0.00 sec)
But I want result as :
+--------------+-----------------------------------------------------+----------------+---------------+---------+------------+---------------------+
| follow_up_id | feedback_open | feedback_close | reminder_date | stage | conclusion | max(l.logs_time) |
+--------------+-----------------------------------------------------+----------------+---------------+---------+------------+---------------------+
| 2 | FSGDFHFGHFG | NULL | 2017-09-20 | Enquiry | Call Back | 2017-09-20 19:10:41 |
| 4 | Call back tender stage update date from 28 to 30 | NULL | NULL | Tender | Next | 2017-09-21 12:36:16 |
| 5 | Metting follow up for next meeting | NULL | 2017-10-02 | Meeting | Call Back | 2017-09-21 12:38:30 |
+--------------+-----------------------------------------------------+----------------+---------------+---------+------------+---------------------+
3 rows in set (0.00 sec)
I'm not able to JOIN and group by to get required result.
column conclusion_id and stage_id of table follow_up are referring to code_id of table allcode.
Question :
the result I want is to be
group by stage_id,
order by srno of allcode and
last/recent follow_up_id of follow_up table
DEMO Includes my answer, original question with full group by needed, and Reupal's answer in demo. You were missing the values in your sample data for conclusionID so I just created them based on ID (now updated to ISO, Callback but missing 98.)
and my results don't match yours in this column; but I believe your expected results are in error.
Seems like you want the max follow_up_ID for each stage_ID when multiple stage_ID's exist
This can be handled by a derived table/inline view getting that max follow_UP_ID grouped by the stage_ID and a joining it back to your set. to limit results to include only the max follow_Up_ID by stage_Id.
I'm also not a fan of mySQL's extended group by and prefer including all columns not aggregated in the select in the group by. Using the extended group by tends to hide potential problems. In this case grouping by just the ast.code_name allowed the engine to select a non distinct value from the other columns. You ended up not getting the desired results and furthermore it hide the fact you would get multiple records in your query were it not for the extended group by use/misuse.
SELECT f.follow_up_id,f.feedback_open, f.feedback_close, f.reminder_date,
ast.code_name as stage, ac.code_name as conclusion, max(l.logs_time)
from follow_up f
join logs l on l.tran_id = f.follow_up_id
join allcode ast on ast.code_id = f.stage_id
join allcode ac on ac.code_id = f.conclusion_id
JOIN SELECT max(follow_up_ID) MFID, stage_ID
FROM follow_up
GROUP BY stage_ID) Z
on f.follow_up_ID = Z.MFID
and F.Stage_ID = Z.Stage_ID
WHERE l.transaction='FLWUP' and f.client_id = 101
GROUP BY f.follow_up_id,f.feedback_open, f.feedback_close, f.reminder_date,
ast.code_name , ac.code_name
ORDER BY ast.srno;
Try below, notice ordering and group by sequence.
select f.follow_up_id,f.feedback_open, f.feedback_close, f.reminder_date,
ast.code_name as stage, ac.code_name as conclusion, max(l.logs_time)
from follow_up f
join logs l on l.tran_id = f.follow_up_id
join allcode ast on ast.code_id = f.stage_id
join allcode ac on ac.code_id = f.conclusion_id
where l.transaction='FLWUP' and f.client_id = 101
group by follow_up.stage_id order by ast.srno, follow_up.follow_up_id DESC;
This should works, and if its not then you should search like how to set ordering on multiple column.
Ref. article- SQL multiple column ordering
I have table obs
+--------+-------+
| obs_id | name |
+--------+-------|
| 101 | mics |
| 102 | jan |
+--------+-------+
I have table monitoring
+--------+--------+---------+
| mon_id | obs_id | code_id |
+--------+--------+---------+
| 1 | 101 | 201 |
| 2 | 101 | 201 |
| 3 | 101 | 202 |
| 4 | 102 | 201 |
| 5 | 102 | 202 |
+--------+--------+---------+
I have table code
+--------+-----------+
|code_id | code_name |
+--------+-----------|
| 201 | node |
| 202 | java |
| 203 | c++ |
+--------+-----------+
Query result
+--------+--------+---------+-----------+
| obs_id | name | code_id | code_name |
+--------+--------+---------+-----------+
| 101 | mics | 201 | node |
| 102 | jan | 201 | node |
+--------+--------+---------+-----------+
Can someone give me a proper mysql query to come up my result.
select A.obs_id, A.name, M.code_id, C.code_name from obs as A
left join monitoring as M on M.obs_id = A.obs_id
left join code as C on C.code_id = M.code_id
The return of my query is more than 2 or it is not what I want as a result.
As per your result ,its look like you want to results for only 'node' .
Then query will be look like below :
CREATE PROCEDURE GETDATA
AS
#CodeId int=0
BEGIN
select DISTINCT A.obs_id, A.name, M.code_id, C.code_name from obs as A
left join monitoring as M on M.obs_id = A.obs_id
left join code as C on C.code_id = M.code_id WHERE c.code_id=#CodeId
END
Now ,you need to only pass codeID into stored Procedure ,it will be return an output based on CodeID . Its look like dynamic .
The above query will give result as you required.
If you want to get distinct data for all code, then just remove where condition.
Thanks .
I was reading about the right outer join from tutorialspoint. I know that when a right outer join is performed the first thing that happens is an inner join of the two tables and then any rows in the right table that are missing in the left table are given null values.
Example from tutorial:
Customers table:
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
| 7 | Muffy | 24 | Indore | 10000.00 |
+----+----------+-----+-----------+----------+
Orders table:
+-----+---------------------+-------------+--------+
|OID | DATE | CUSTOMER_ID | AMOUNT |
+-----+---------------------+-------------+--------+
| 102 | 2009-10-08 00:00:00 | 3 | 3000 |
| 100 | 2009-10-08 00:00:00 | 3 | 1500 |
| 101 | 2009-11-20 00:00:00 | 2 | 1560 |
| 103 | 2008-05-20 00:00:00 | 4 | 2060 |
+-----+---------------------+-------------+--------+
Query:
SELECT ID, NAME, AMOUNT, DATE
FROM CUSTOMERS
RIGHT JOIN ORDERS
ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;
Result:
+------+----------+--------+---------------------+
| ID | NAME | AMOUNT | DATE |
+------+----------+--------+---------------------+
| 3 | kaushik | 3000 | 2009-10-08 00:00:00 |
| 3 | kaushik | 1500 | 2009-10-08 00:00:00 |
| 2 | Khilan | 1560 | 2009-11-20 00:00:00 |
| 4 | Chaitali | 2060 | 2008-05-20 00:00:00 |
+------+----------+--------+---------------------+
Why is the result of the right outer join the same as the original right table? How is this right join in anyway useful? I see it as pointless.
This isn't a useful query for RIGHT JOIN. Since all orders should have a valid customer (in fact, there should be a foreign key relationship between the Order and Customers tables), there will never be an order with no matching customer, so you'll never get any null values added.
I think they included this query just to contrast it with the almost identical query on the LEFT JOIN and FULL JOIN pages of the tutorial. Those queries show all orders, as well as all customers that don't have any orders (they have NULL in the AMOUNT and DATE columns.
To get the equivalent result with RIGHT JOIN you can simply swap the order of the tables:
SELECT ID, NAME, AMOUNT, DATE
FROM ORDERS
RIGHT JOIN CUSTOMERS
ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;
Because LEFT JOIN and RIGHT JOIN are equivalent like this, most programmers just use LEFT JOIN.
This is not the right example in that case.To see something which is there in orders table but not in customers table the id should be something that is not present in customers,such as 8,9 etc.