Free search on multiple tables using JOIN - mysql

I have a DB of Students who have a fullname, a location, and a list of schools they frequented.
"student" table
id | fullname | location
------------------------
"location" table
id | zipcode | city
-------------------
"school" table
id | name
---------
"student_school" table (which holds two foreign keys on school and user to create for each user a list of schools)
id | id_student | id_school
---------------------------
I want to perform a search through the students comparing the search term with student.fullname, location.zipcode, location.city, school.name and return all the students matching one (or more) of these conditions.
Note that student can have a null location, so we need an extern join.

Here is example of matching based on regular expressions:
SELECT distinct s.id, s.fullname
FROM student_school ss
JOIN student s ON s.id = ss.id_student
LEFT JOIN LOCATION l ON s.LOCATION = l.id
JOIN school sc ON ss.id_school = sc.id
WHERE (s.fullname RLIKE 'Sasha.*') or
(ifnull(l.zipcode RLIKE '100.*', 0)) or
(ifnull(l.city RLIKE 'New.*', 0)) or
(sc.name RLIKE '.*2')
And here is complete SQL fiddle
So the general idea is to join all student data, filter rows matching at least one criterion and use distinct to group data and avoid duplicating of results.
Update:
To include students with no school records you may use following FROM phrase:
student_school ss
RIGHT JOIN student s ON s.id = ss.id_student
LEFT JOIN LOCATION l ON s.LOCATION = l.id
LEFT JOIN school sc ON ss.id_school = sc.id

Related

my sql output the same data more than one time when i use select statement

I created three tables "student" and "course" and "lecturer" and I inserted data into them.
Now I want to retrieve some data by select.
When I want to show: Subject taken by Kumar
SELECT STUDENT.NAME, COURSE.SUBJECT1, COURSE.SUBJECT2, COURSE.SUBJECT3
FROM STUDENT,COURSE
WHERE STUDENT.COURSE = COURSE.COURSE = 'MLVK'
it repeats the data more than one time.
I hope anyone help me
All the best
Learn to use proper, explicit, standard JOIN syntax.
And, table aliases:
SELECT s.NAME, c.SUBJECT1, c.SUBJECT2, c.SUBJECT3
FROM STUDENT s JOIN
COURSE c
ON s.COURSE = c.COURSE
WHERE c.COURSE = 'MLVK'
If I were going to use these tables to pick subjects taken by Kumar, I would write something like:
SELECT
s.name, c.course, c.subject1, c.subject2, c.subject3
FROM
student as s
LEFT JOIN course as c on c.course = s.course
WHERE
s.no_matrik = '23456'
GROUP BY
s.name, c.course, c.subject1, c.subject2, c.subject3
I think this version makes the intent slightly more clear (pick subject for a particular student, Kumar) than the previous answer (select subjects for any student having course = 'MLVK'). This answer will also return information for Kumar even if he has no course value in the Student table (pre-enrollment?).
First of all I would suggest that to model your data properly in BCNF form, where you should have modelled another table to persist subjects and map the lecturer who take that subject.
Ex: (Subject Table)
SubjectId LECT_ID
---------- ------------
TT234 L123
TT235 L003
and, your Course table would be more of course to subject mapping, like:
CourseName SubjectId
------------- --------------
DTM TT235
DTM TT695
...
then you use query as:
Select sub.SubjectId, l.NAME
From
Student s JOIN
Course c
on c.CourseName = s.COURSE
JOIN Subject sub
on sub.SubjectId = c.SubjectId
JOIN Lecturer l
on l.LECT_ID = sub.Lecturer
Where s.NAME = 'Aminah'
the above query will result as:
SubjectId NAME
--------- ----------
PP563 Ahmad
SS003 Ahmad
PP999 John
as Ahmad happens to be teaching 2 subjects in course DPG. but if you wish to report distinct Lecturers for Aminah, you can change query as:
SELECT NAME FROM Lecturer where LECT_ID
in (
Select l.LET_ID
From
Student s JOIN
Course c
on c.CourseName = s.COURSE
JOIN Subject sub
on sub.SubjectId = c.SubjectId
JOIN Lecturer l
on l.LECT_ID = sub.LECT_ID
Where s.NAME = 'Aminah'
) a

SQL COUNT Return Wrong Number

so I have a problem with my query. I have 2 tables:
courses:
The user_id in this table is the instructor of the course.
-----------------------------------------------------------------------
| course_id | user_id | course_name | other information |
-----------------------------------------------------------------------
| 6 | 1 | My Course 1 | ... |
-----------------------------------------------------------------------
my_courses:
The user_id in this table is a student of the course.
--------------------------------------------------
| user_id | course_id | created_at |
--------------------------------------------------
| 5 | 6 | [UNIX_TIMESTAMP] |
--------------------------------------------------
The my_courses contains the number of people that have joined that course. I want to get all the course info as well as the number of people that have joined a course. Everything returns as expected except the number of people that joined a course. This is the query I'm using:
SELECT
courses.*,
users.name, //This is the name of the instructor
users.last_name, //This is the last name of the instructor
COUNT(my_courses.user_id) as count_students
FROM courses
LEFT JOIN users
ON courses.user_id = courses.user_id
LEFT JOIN my_courses
ON courses.course_id = my_courses.course_id
WHERE courses.course_id = '6'
Like I said, this query returns the course info like normal but returns 3 as count_students when it should only return 1. Does anyone know why this is happening? Any help is greatly appreciated.
It's probably because of the JOIN condition for users. It should be:
LEFT JOIN users
ON courses.user_id = users.user_id
You should also add a GROUP BY clause in your query:
SELECT
c.*,
u.name,
u.last_name,
COUNT(mc.user_id) AS count_students
FROM courses c
LEFT JOIN users u
ON c.user_id = u.user_id
LEFT JOIN my_courses mc
ON c.course_id = mc.course_id
WHERE c.course_id = '6'
GROUP BY
<columns not in the aggregate function>
Additionally, alias your tables to improve readability.
JOIN operations cause combinatorial multiplication of rows. You need to summarize the student count from its own table like so.
SELECT course_id, COUNT(*) students
FROM my_courses
GROUP BY course_id
That gives you a result set with either one or zero rows per course_id. You can then join it to the rest of your query.
SELECT courses.*,
users.name, //This is the name of the instructor
users.last_name, //This is the last name of the instructor
aggr.count_students
FROM courses
LEFT JOIN users ON courses.user_id = courses.user_id
LEFT JOIN (
SELECT course_id, COUNT(*) students
FROM my_courses
GROUP BY course_id
) aggr ON courses.course_id = aggr.course_id
WHERE courses.course_id = '6'
That way you'll avoid multiple-counting your students for courses with, perhaps, more than one instructor.

Select rows from table and additional data form other table if exists

I have a hard time figuring out how to write a query that selects all rows that matches certain conditions from one table and extends the rows with data from another table if there is data that matches another set of conditions.
Table: books
id
school
isbn
name
Table: orders
id
school
department
isbn
quantity
The query I have is:
SELECT orders.*, books.name FROM orders
LEFT JOIN books ON orders.isbn = books.isbn
WHERE orders.school = 1 AND orders.department = 2
AND books.school = 1
Now, the problem is that if a school hasn't added their books, isbn and names into the books table I'd still like to have the orders.* data returned with books.name set to null or something similar. Now I get zero rows instead. Is there a way to do this with one query?
Move
and books.school = 1
from the where clause to the from clause.
left join books on orders.isbn = books.isbn
and books.school = 1
Edit starts here
for raheel who says it doesn't matter. Using the world database that came with the MySQL I downloaded, this query
select c.name, city.name cityname
from country c left join city on c.code = city.countrycode
AND city.name = 'toronto'
order by cityname;
returns 239 rows. This query:
select c.name, city.name cityname
from country c left join city on c.code = city.countrycode
WHERE city.name = 'toronto'
order by cityname;
returns 1 row. I think it matters

Getting data from multiple tables using joins

I have various tables like
Student
primary id , students name, course
Papers
paper id, papername, course, semester, type
StudentOptions
primary id, studentid (foreign key - reference student id) and paperid (foreign key - references paper id)
StudentsTerm
studentid (foreign key- references student id) and student semester
Now the kind of result i want is,
I want to choose a course then the term, which will give me the number of papers/subject it has with their types (Mandatory/Optional) and with that i want to have the count of number of students studying those papers from all these tables.
I don't wanna create any view or stuff, Just a normal select query will do.
The query i am running is :
SELECT p_name,
p_id,
type,
Count(sps.studentid) AS counts
FROM students,
str,
papers
LEFT JOIN sps
ON sps.paperid = papers.p_id
WHERE sps.studentid = students.studentid
AND students.studentid = str.studentid
AND sps.studentid = str.studentid
AND str.semesterid = p_semid
AND str.sessionid = 12
AND students.course = c_id
AND c_id = 6
AND p_semid = 1
GROUP BY p_id
As better practice, if you are going to be using explicit JOIN syntax, then don't use implicit syntax. In the query you posted above, you select from papers, but you don't use it anywhere. Also, your column names are slightly ambiguous. If it's easier, alias each table using a single letter, or explicitly prefix the column names. If you're using an aggregate with GROUP BY, you cannot select columns which are not in the group.
Let's assume this is your ER diagram:
Let's first join all the tables:
SELECT a.id, a.name
FROM student a
JOIN str b ON b.student_id = a.id
JOIN sps c ON c.student_id = a.id
JOIN papers d ON d.id = c.paper_id
Now you wish to find the number of students studying papers from a specific course and type:
SELECT a.id, a.name
FROM student a
JOIN str b ON b.student_id = a.id
JOIN sps c ON c.student_id = a.id
JOIN papers d ON d.id = c.paper_id
WHERE b.semester = 12
AND d.course = 6
Because your attributes are ambigiuous, it is hard to tell what tables they are coming from. If you can set up the structure and sample data on SQL Fiddle, we could help you better.

mysql query help to fetch data by joining multiple tables

I have following tables:
base:
id | domain
extended:
id | domain | country_code
countries:
id | country_code | country_name
banned_domains:
id | domain
I will have several thousands (more than 500K) of domains in banned_domains. Now I need to fetch data "domain, country_code and country_name" which do not exist on banned_domains list. I am not so good at the MySQL JOINS, can anyone guide me for the proper query.
SELECT b.domain, ex.country_code, c.country_name FROM base b
INNER JOIN extended ex ON b.domain=ex.domain
INNER JOIN countries c ON ex.country_code=c.country_code
WHERE b.domain NOT IN (SELECT domain FROM banned_domains);
You can use this query .
select b.domain , e.country_code , c.country_name from base b join extended e on b.domain = e.domain join countries c on e.country_code = c.country_code and b.domain not in (select domain from banned_domains);
Try this link http://sqlfiddle.com/#!2/f78ea/1 .