What is this self join and why do we need this self join?. I have till date never used self joins.
See if these links helps you...
http://www.udel.edu/evelyn/SQL-Class3/SQL3_self.html
http://awads.net/wp/2006/07/11/back-to-basics-self-joins/
http://www.sqltutorial.org/sqlselfjoin.aspx
Good Luck!!!
there are number of reasons, and tons of examples are available on web
http://www.udel.edu/evelyn/SQL-Class3/SQL3_self.html
mysql> SELECT * FROM pr WHERE id>80;
+----+------+--------+
| id | ids | status |
+----+------+--------+
| 81 | 4 | 4 |
| 82 | 2 | 3 |
| 83 | 2 | 4 |
+----+------+--------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM pr WHERE id<18;
+----+------+--------+
| id | ids | status |
+----+------+--------+
| 1 | 1 | 1 |
| 5 | NULL | 2 |
+----+------+--------+
2 rows in set (0.01 sec)
identical requests :
mysql> SELECT * FROM pr AS t1 ,pr AS t2 WHERE t1.id<18 AND t2.id>80;
+----+------+--------+----+------+--------+
| id | ids | status | id | ids | status |
+----+------+--------+----+------+--------+
| 1 | 1 | 1 | 81 | 4 | 4 |
| 5 | NULL | 2 | 81 | 4 | 4 |
| 1 | 1 | 1 | 82 | 2 | 3 |
| 5 | NULL | 2 | 82 | 2 | 3 |
| 1 | 1 | 1 | 83 | 2 | 4 |
| 5 | NULL | 2 | 83 | 2 | 4 |
+----+------+--------+----+------+--------+
6 rows in set (0.00 sec)
mysql> SELECT * FROM pr AS t1 JOIN pr AS t2 ON t1.id<18 AND t2.id>80;
+----+------+--------+----+------+--------+
| id | ids | status | id | ids | status |
+----+------+--------+----+------+--------+
| 1 | 1 | 1 | 81 | 4 | 4 |
| 5 | NULL | 2 | 81 | 4 | 4 |
| 1 | 1 | 1 | 82 | 2 | 3 |
| 5 | NULL | 2 | 82 | 2 | 3 |
| 1 | 1 | 1 | 83 | 2 | 4 |
| 5 | NULL | 2 | 83 | 2 | 4 |
+----+------+--------+----+------+--------+
6 rows in set (0.00 sec)
Related
im new with SQL. i know to how select a list with limit comand. but that way need a value to select. what if i want select a list from random id to the last. exemple:
I want to select a list with id from 4 -> last of row (cuz i dont know whats last id)
select * from thing1 where id>=4 order by rand();
where thing1 is your table name. How you seed your random number generator (RNG) is up to you.
+----+---------+------------+
| id | conn_id | read_date |
+----+---------+------------+
| 11 | 3 | 2013-02-21 |
| 5 | 1 | 2012-02-21 |
| 8 | 5 | 2010-12-21 |
| 15 | 7 | 2019-12-21 |
| 14 | 6 | 2019-12-21 |
| 13 | 5 | 2016-02-21 |
| 4 | 2 | 2010-12-21 |
| 7 | 2 | 2014-02-21 |
| 6 | 2 | 2007-12-21 |
| 12 | 4 | 2014-02-21 |
| 16 | 8 | 2010-12-21 |
| 9 | 3 | 2010-12-21 |
| 10 | 4 | 2010-12-21 |
+----+---------+------------+
13 rows in set (0.14 sec)
mysql> select * from thing1 where id>=4 order by rand();
+----+---------+------------+
| id | conn_id | read_date |
+----+---------+------------+
| 13 | 5 | 2016-02-21 |
| 6 | 2 | 2007-12-21 |
| 10 | 4 | 2010-12-21 |
| 16 | 8 | 2010-12-21 |
| 14 | 6 | 2019-12-21 |
| 5 | 1 | 2012-02-21 |
| 7 | 2 | 2014-02-21 |
| 11 | 3 | 2013-02-21 |
| 12 | 4 | 2014-02-21 |
| 4 | 2 | 2010-12-21 |
| 8 | 5 | 2010-12-21 |
| 9 | 3 | 2010-12-21 |
| 15 | 7 | 2019-12-21 |
+----+---------+------------+
13 rows in set (0.02 sec)
mysql> select * from thing1 where id>=4 order by rand();
+----+---------+------------+
| id | conn_id | read_date |
+----+---------+------------+
| 10 | 4 | 2010-12-21 |
| 4 | 2 | 2010-12-21 |
| 6 | 2 | 2007-12-21 |
| 7 | 2 | 2014-02-21 |
| 5 | 1 | 2012-02-21 |
| 9 | 3 | 2010-12-21 |
| 12 | 4 | 2014-02-21 |
| 16 | 8 | 2010-12-21 |
| 8 | 5 | 2010-12-21 |
| 15 | 7 | 2019-12-21 |
| 13 | 5 | 2016-02-21 |
| 14 | 6 | 2019-12-21 |
| 11 | 3 | 2013-02-21 |
+----+---------+------------+
13 rows in set (0.05 sec)
Stored Proc
To have starting random position, until the end, random ordering
-- drop procedure getRandomStartToEnd;
delimiter $$
create procedure getRandomStartToEnd()
BEGIN
declare theCount int;
declare theStart int;
select count(*) into theCount from thing1;
set #theStart:=floor((rand()*#theCount)+1);
select * from thing1 where id>=#theStart order by rand();
END
$$
call getRandomStartToEnd; -- call stored proc
My tables :
mysql> select * from professor;
+-------+--------+--------+--------+------+
| empid | name | status | salary | age |
+-------+--------+--------+--------+------+
| 1 | Arun | 1 | 2000 | 23 |
| 2 | Benoy | 0 | 3000 | 25 |
| 3 | Chacko | 1 | 1000 | 36 |
| 4 | Divin | 0 | 5000 | 32 |
| 5 | Edwin | 1 | 2500 | 55 |
| 7 | George | 0 | 1500 | 46 |
+-------+--------+--------+--------+------+
6 rows in set (0.00 sec)
mysql> select * from works;
+----------+-------+---------+
| courseid | empid | classid |
+----------+-------+---------+
| 1 | 1 | 10 |
| 2 | 2 | 9 |
| 3 | 3 | 8 |
| 4 | 4 | 10 |
| 5 | 5 | 9 |
| 6 | 1 | 9 |
| 2 | 3 | 10 |
| 2 | 1 | 7 |
| 4 | 2 | 6 |
| 2 | 4 | 6 |
| 2 | 5 | 2 |
| 7 | 5 | 6 |
| 3 | 5 | 2 |
| 6 | 4 | 10 |
+----------+-------+---------+
14 rows in set (0.00 sec)
mysql> select * from course;
+----------+------------+--------+
| courseid | coursename | points |
+----------+------------+--------+
| 1 | Maths | 5 |
| 2 | Science | 1 |
| 3 | English | 6 |
| 4 | Social | 4 |
| 5 | Malayalam | 20 |
| 6 | Arts | 25 |
| 7 | Biology | 20 |
+----------+------------+--------+
7 rows in set (0.00 sec)
Question is :
Return the name(s) of the professor(s) who taught the most number of
courses in Class 10
Query i tried is :
select professor.name,works.courseid,works.empid,works.classid from professor
inner join works
on professor.empid=works.empid
where works.classid=10
group by works.courseid
I know its imcomplete/incorrect. Pls help me to the required result.
select
professor.name, count(works.courseid)
from
works
inner join
professor on
professor.empid = works.empid
where
work.classid = 10
group by
professor.name
order by count(works.courseid) desc
limit 1
change this in your select statment
works.courseid
to
count(works.courseid) as courseid
These are my tables
mysql> select * from professor;
+-------+--------+--------+--------+------+
| empid | name | status | salary | age |
+-------+--------+--------+--------+------+
| 1 | Arun | 1 | 2000 | 23 |
| 2 | Benoy | 0 | 3000 | 25 |
| 3 | Chacko | 1 | 1000 | 36 |
| 4 | Divin | 0 | 5000 | 32 |
| 5 | Edwin | 1 | 2500 | 55 |
+-------+--------+--------+--------+------+
5 rows in set (0.00 sec)
mysql> select * from works;
+----------+-------+---------+
| courseid | empid | classid |
+----------+-------+---------+
| 1 | 1 | 10 |
| 2 | 2 | 9 |
| 3 | 3 | 8 |
| 4 | 4 | 10 |
| 5 | 5 | 9 |
| 6 | 1 | 9 |
| 2 | 3 | 10 |
| 2 | 1 | 7 |
| 4 | 2 | 6 |
| 7 | 5 | 6 |
| 3 | 5 | 2 |
| 2 | 4 | 6 |
| 2 | 5 | 2 |
+----------+-------+---------+
15 rows in set (0.00 sec)
mysql> select * from course;
+----------+------------+--------+
| courseid | coursename | points |
+----------+------------+--------+
| 1 | Maths | 4 |
| 2 | Science | 4 |
| 3 | English | 85 |
| 4 | Social | 4 |
| 5 | Malayalam | 99 |
| 6 | Arts | 40 |
| 7 | Biology | 100 |
+----------+------------+--------+
7 rows in set (0.00 sec)
Question is :
Return the names of full professors who have taught at least two courses in one Class
My query is :
select professor.name from professor
inner join works
on professor.empid=works.empid
group by works.empid
having count(distinct works.courseid)>=2
The ouput I get now is :
Arun
Benoy
Chacko
Divin
Edwin
I am supposed to get the ouput as 'Edwin' as he is the only person who has taught 2 subjects in the same class. Pls help
you must consider your group by is wrong change it to this
group by classid,works.empid
like that you will count courseid in classid .
i got these tables in my dbpre_exer5;//mysql wampserver2.2
+-----------------------+
| Tables_in_dbpre_exer5 |
+-----------------------+
| tblcourse |
| tblcutoff |
| tblgrades |
| tblstud |
| tblsub |
+-----------------------+
now, i just want to ask how will i be able to get these outputs considering the usage of stored procedure.
the output is:
+---------+----------------+---------------+-------+
| Gender | With Failure | W/out Failure | Total |
+---------+----------------+---------------+-------+
| Male | 1 | 1 | 2 |
| Female | 2 | 1 | 3 |
+---------+----------------+---------------+-------+
by the way here is the enter code here;
**
mysql> select * from tblcourse;
+-----------+------------------------+
| course_id | course_name |
+-----------+------------------------+
| 1 | Information Technology |
| 2 | Computer Science |
+-----------+------------------------+
2 rows in set (0.00 sec)
mysql> select * from tblgrades;
+---------+--------+-------+
| stud_id | sub_id | grade |
+---------+--------+-------+
| 1 | 1 | 80 |
| 1 | 2 | 78 |
| 2 | 2 | 75 |
| 2 | 3 | 84 |
| 3 | 1 | 81 |
| 3 | 3 | 90 |
| 4 | 1 | 74 |
| 4 | 2 | 77 |
| 5 | 2 | 76 |
| 5 | 3 | 81 |
+---------+--------+-------+
10 rows in set (0.00 sec)
mysql> select * from tblcourse;
+-----------+------------------------+
| course_id | course_name |
+-----------+------------------------+
| 1 | Information Technology |
| 2 | Computer Science |
+-----------+------------------------+
2 rows in set (0.00 sec)
mysql> select * from tblcutoff;
+-----------+
| passgrade |
+-----------+
| 78 |
+-----------+
1 row in set (0.00 sec)
mysql> select * from tblgrades;
+---------+--------+-------+
| stud_id | sub_id | grade |
+---------+--------+-------+
| 1 | 1 | 80 |
| 1 | 2 | 78 |
| 2 | 2 | 75 |
| 2 | 3 | 84 |
| 3 | 1 | 81 |
| 3 | 3 | 90 |
| 4 | 1 | 74 |
| 4 | 2 | 77 |
| 5 | 2 | 76 |
| 5 | 3 | 81 |
+---------+--------+-------+
10 rows in set (0.00 sec)
mysql> select * from tblstud;
+---------+-------------------+--------+-----------+
| stud_id | stud_name | gender | course_id |
+---------+-------------------+--------+-----------+
| 1 | Angelina Jolie | F | 1 |
| 2 | Jennifer Garner | F | 1 |
| 3 | Liam Neeson | M | 2 |
| 4 | Paul Walker | M | 2 |
| 5 | Jennifer Lawrence | F | 2 |
+---------+-------------------+--------+-----------+
5 rows in set (0.00 sec)
mysql> select * from tblsub;
+--------+------------+
| sub_id | sub_name |
+--------+------------+
| 1 | Math 1 |
| 2 | English 1 |
| 3 | Filipino 1 |
+--------+------------+
3 rows in set (0.00 sec)
mysql>
**
my first problem is having the results "Male" and "Female" under gender..
any help? thanks a lot.
UPDATED
SELECT gender,
SUM(failure) `With failure`,
COUNT(*) - SUM(failure) `Without failure`,
COUNT(*) total
FROM
(
SELECT s.stud_id,
CASE WHEN s.gender = 'M' THEN 'Male' ELSE 'Female' END gender,
MAX(CASE WHEN g.grade < c.passgrade THEN 1 ELSE 0 END) failure
FROM tblgrades g JOIN tblstud s
ON g.stud_id = s.stud_id CROSS JOIN tblcutoff c
GROUP BY s.stud_id
) q
GROUP BY gender
Sample output:
| GENDER | WITH FAILURE | WITHOUT FAILURE | TOTAL |
---------------------------------------------------
| Female | 2 | 1 | 3 |
| Male | 1 | 1 | 2 |
Here is SQLFiddle demo
You can use a simple case statement:
CASE WHEN 'F' THEN SELECT 'Female' ELSE SELECT 'Male'
Further reading
In this case, a left join is the same as a right join?
mysql>
mysql>
mysql> use usenet;show tables;describe ARTICLE;describe NEWSGROUP;
Database changed
+------------------+
| Tables_in_usenet |
+------------------+
| ARTICLE |
| NEWSGROUP |
+------------------+
2 rows in set (0.00 sec)
+---------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| MESSAGENUMBER | int(11) | YES | | NULL | |
| NEWSGROUP_ID | bigint(20) | YES | MUL | NULL | |
+---------------+------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| NEWSGROUP | varchar(255) | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql>
mysql> select * from ARTICLE right join NEWSGROUP on ARTICLE.NEWSGROUP_ID=NEWSGROUP.ID;
+------+---------------+--------------+----+-------------------------------+
| ID | MESSAGENUMBER | NEWSGROUP_ID | ID | NEWSGROUP |
+------+---------------+--------------+----+-------------------------------+
| 1 | 4 | 1 | 1 | gwene.com.androidcentral |
| 2 | 5 | 1 | 1 | gwene.com.androidcentral |
| 3 | 6 | 1 | 1 | gwene.com.androidcentral |
| 4 | 7 | 1 | 1 | gwene.com.androidcentral |
| 5 | 8 | 1 | 1 | gwene.com.androidcentral |
| 6 | 9 | 1 | 1 | gwene.com.androidcentral |
| 7 | 10 | 1 | 1 | gwene.com.androidcentral |
| 8 | 11 | 1 | 1 | gwene.com.androidcentral |
| 9 | 4 | 2 | 2 | gwene.com.blogspot.emacsworld |
| 10 | 4 | 3 | 3 | gwene.com.blogspot.googlecode |
| 11 | 5 | 3 | 3 | gwene.com.blogspot.googlecode |
| 12 | 6 | 3 | 3 | gwene.com.blogspot.googlecode |
| 13 | 7 | 3 | 3 | gwene.com.blogspot.googlecode |
| 14 | 8 | 3 | 3 | gwene.com.blogspot.googlecode |
| 15 | 9 | 3 | 3 | gwene.com.blogspot.googlecode |
| 16 | 10 | 3 | 3 | gwene.com.blogspot.googlecode |
| 17 | 11 | 3 | 3 | gwene.com.blogspot.googlecode |
| 18 | 4 | 4 | 4 | gwene.com.economist |
| 19 | 5 | 4 | 4 | gwene.com.economist |
| 20 | 6 | 4 | 4 | gwene.com.economist |
| 21 | 7 | 4 | 4 | gwene.com.economist |
| 22 | 8 | 4 | 4 | gwene.com.economist |
| 23 | 9 | 4 | 4 | gwene.com.economist |
| 24 | 10 | 4 | 4 | gwene.com.economist |
| 25 | 11 | 4 | 4 | gwene.com.economist |
+------+---------------+--------------+----+-------------------------------+
25 rows in set (0.00 sec)
mysql>
mysql> select * from ARTICLE left join NEWSGROUP on ARTICLE.NEWSGROUP_ID=NEWSGROUP.ID;
+----+---------------+--------------+------+-------------------------------+
| ID | MESSAGENUMBER | NEWSGROUP_ID | ID | NEWSGROUP |
+----+---------------+--------------+------+-------------------------------+
| 1 | 4 | 1 | 1 | gwene.com.androidcentral |
| 2 | 5 | 1 | 1 | gwene.com.androidcentral |
| 3 | 6 | 1 | 1 | gwene.com.androidcentral |
| 4 | 7 | 1 | 1 | gwene.com.androidcentral |
| 5 | 8 | 1 | 1 | gwene.com.androidcentral |
| 6 | 9 | 1 | 1 | gwene.com.androidcentral |
| 7 | 10 | 1 | 1 | gwene.com.androidcentral |
| 8 | 11 | 1 | 1 | gwene.com.androidcentral |
| 9 | 4 | 2 | 2 | gwene.com.blogspot.emacsworld |
| 10 | 4 | 3 | 3 | gwene.com.blogspot.googlecode |
| 11 | 5 | 3 | 3 | gwene.com.blogspot.googlecode |
| 12 | 6 | 3 | 3 | gwene.com.blogspot.googlecode |
| 13 | 7 | 3 | 3 | gwene.com.blogspot.googlecode |
| 14 | 8 | 3 | 3 | gwene.com.blogspot.googlecode |
| 15 | 9 | 3 | 3 | gwene.com.blogspot.googlecode |
| 16 | 10 | 3 | 3 | gwene.com.blogspot.googlecode |
| 17 | 11 | 3 | 3 | gwene.com.blogspot.googlecode |
| 18 | 4 | 4 | 4 | gwene.com.economist |
| 19 | 5 | 4 | 4 | gwene.com.economist |
| 20 | 6 | 4 | 4 | gwene.com.economist |
| 21 | 7 | 4 | 4 | gwene.com.economist |
| 22 | 8 | 4 | 4 | gwene.com.economist |
| 23 | 9 | 4 | 4 | gwene.com.economist |
| 24 | 10 | 4 | 4 | gwene.com.economist |
| 25 | 11 | 4 | 4 | gwene.com.economist |
+----+---------------+--------------+------+-------------------------------+
25 rows in set (0.00 sec)
mysql>
mysql>
Not really, because RIGHT JOIN and LEFT JOIN are symmetric. That is:
A LEFT JOIN B = B RIGHT JOIN A
RIGHT JOIN is merely syntactic sugar. The optimizer can rewrite a right join to a left join:
mysql> explain extended select * from t right join t t2 using (c1)\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t2
type: index
possible_keys: NULL
key: c2
key_len: 5
ref: NULL
rows: 4201
filtered: 100.00
Extra: Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: t
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: test.t2.c1
rows: 1
filtered: 100.00
Extra:
2 rows in set, 1 warning (0.00 sec)
Note the LEFT JOIN in the optimizer re-write (the tables are swapped):
mysql> show warnings\G
*************************** 1. row ***************************
Level: Note
Code: 1003
Message: select `test`.`t2`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2`,`test`.`t`.`c2` AS
`c2` from `test`.`t` `t2` left join `test`.`t` on((`test`.`t`.`c1` = `test`.`t2`.`c1`)) where 1
1 row in set (0.00 sec)
Notice that (A RIGHT JOIN B != A LEFT JOIN B) unless (A INNER JOIN B = A LEFT JOIN B). This is because A RIGHT JOIN B is not symmetrical with A LEFT JOIN B (it is symmetrical with B LEFT JOIN A).
In your case, A RIGHT JOIN B will be the same as A LEFT JOIN B unless there are NULL values in the columns you are joining. If there are NULL values, then A LEFT JOIN B will NOT be the same as A RIGHT JOIN B. If you add new articles without adding the associated newsgroup (or vice-versa) then the results would change too.
Codeproject has this image which explains the simple basics of SQL joins, taken from: http://www.codeproject.com/KB/database/Visual_SQL_Joins.aspx SQL joins explained
With your current data, yes they are the same. However as NEWSGROUP_ID is nullable then they could be different as the data changes.
Personally I always use LEFT JOINs if possible (from primary table to child table), in fact I have only needed to use a RIGHT JOIN a couple of times in over 6 years of SQL development!