Cross table query - mysql

I have three tables.
course
idcourse
name
mark
idmark
idstudent
idcourse
mark
student
idstudent
name
How to cross a query to such a result?
result
table Header
studentid course1 course2 ... courseN
id1 mark1 mark2 ... markN
id2 mark1 mark2 ... markN
id3 mark1 mark2 ... markN

Best I can think if is to use the group_concat function.
Because a variable number of columns is just a maintenance nightmare.
You can strip the values from the coursegrades field apart by exploding the list in php or whatever comma separator you have in your client.
/*First make a list of coursenames for the header.*/
SELECT 'studentid' as idstudent
, 'studentname' as studentname
, GROUP_CONCAT(course.name ORDER BY couselist.idcourse) as coursegrades
FROM course
INNER JOIN (SELECT DISTINCT idcourse FROM mark) courselist
ON (courselist.idcourse = course.idcourse)
UNION ALL
/*UNION ALL this with a list of grades per course*/
SELECT idstudent
, student.name as studentname
, GROUP_CONCAT(IFNULL(mark.mark,'') ORDER BY courselist.idcourse) as coursegrades
FROM course
INNER JOIN (SELECT DISTINCT idcourse FROM mark) courselist
ON (courselist.idcourse = course.idcourse)
LEFT JOIN mark ON (mark.idcourse = courselist.idcourse)
INNER JOIN student ON (student.idstudent = mark.idstudent)
GROUP BY student

First you should have many-to-one foreign key relationships to insure that the idstudent field in the tables depending on the student table idstudent field (mark, course) match up.
To answer your specific question, it's not possible to return a result like this from the database client. Maybe if you wrote something as a procedure, but not with basic SQL. The best way to get the results you want is to do a simple query on the mark table to get the idstudent and mark fields and then manipulate them externally in another language.
So the query would be like this:
SELECT marks.idstudent, marks.mark, courses.name FROM marks,courses
WHERE marks.idcourse=courses.idcourse;
And you can display the results using an external program written in PHP or Python, for example.

Related

Does using nested queries adds semantics to the sql query over simple query

create table students(id int,
name varchar(20),
dept varchar(10),
salary int default 10000
);
Insert into students values(1,'Ram','HR',10000);
Insert into students values(2,'Amrit','Mrkt',20000);
Insert into students values(3,'Ravi','HR',30000);
Insert into students values(4,'Raju','finance',40000);
Query which my tutor told me:
select name from employee where dept in(select dept from emp group by dept having count(*)<2);
he told that we should only use that attribute with select statement which has been used in group by and other attributes cannot be used.
But the following query also works:
select name from employee group by dept having count(*)<2;
is my query correct or wrong? if it is correct what is the advantage of using it as nested query than simple query?
If you have only one matching row, then you can use:
select max(name)
from employee
group by dept
having count(*) = 1;
The having clause guarantees one match. The max() returns the value in the one row.
This is fine, but not very orthodox -- it doesn't generalize very well. The form that your tutor suggests is more generalizable. It will readily adapt to looking for employees in departments with 2 employees or 7 or whatever.

Nested Query Issue

I have two tables, a NextOfKin table and a Course table, the NextOfKin table has the following attributes:
StudentID
ContactTelNo
And the course has this one (only showing relevant attributes):
CourseNo
I am trying to get an output where I show the studentID and contactTelNo for the next of kin of all students on course with courseNo equal to 1001.
This is the code I'm attempting to run
SELECT studentID, contactTelNo
FROM NextOfKin
WHERE courseNo =
(SELECT courseNo
FROM Course
WHERE courseNo = '1001')
I'm currently getting an error message that says "Unkown coloumn 'courseNo' in 'where clause'
where am I going wrong?
p.s I can only used a nested query and not a join
The subquery needs to return student IDs, not course numbers, since that's what's in the NextOfKin table. And you need to use IN rather than = to check for membership in a set:
SELECT studentID, contactTelNo
FROM NextOfKin
WHERE studentID IN
(SELECT studentID
FROM Course
WHERE courseNo = '1001')
Assuming Course also has a StudentID column, you want this:
SELECT NextOfKin.studentID, NextOfKin.contactTelNo
FROM NextOfKin
INNER JOIN Course ON Course.StudentID = NextOfKin.StudentID
WHERE Course.courseNo ='1001'
If Course does NOT have a StudentID column, you're looking at the wrong table. Somewhere you will have a table with columns for both StudentID and CourseNo values. It might be called something like Enrollments or Registrations.

sql table design to fetch records with multiple inclusion and exclusion conditions

We want to select customers based on following parameters i.e. customer should be in:
specific city i.e. cityId=1,2,3...
specific customerId should be excluded i.e. customerId=33,2323,34534...
specific age i.e. 5 years, 7 years, 72 years...
This inclusion & exclusion list can be any long.
How should we design database for this:
Create separate table 'customerInclusionCities' for these inclusion cities and do like:
select * from customers where cityId in (select cityId from customerInclusionCities)
Some we do for age, create table 'customerEligibleAge' with all entries of eligible age entries:
i.e. select * from customers where age in (select age from customerEligibleAge)
and Create separate table 'customerIdToBeExcluded' for excluding customers:
i.e. select * from customers where customerId not in (select customerId from customerIdToBeExcluded)
OR
Create One table with Category and Ids.
i.e. Category1 for cities, Category2 for CustomerIds to be excluded.
Which approach is better, creating one table for these parameters OR creating separate tables for each list i.e. age, customerId, city?
IN ( SELECT ... ) can be very slow. Do your query as a single SELECT without subqueries. I assume all 3 columns are in the same table? (If not, that adds complexity.) The WHERE clause will probably have 3 IN ( constants ) clauses:
SELECT ...
FROM tbl
WHERE cityId IN (1,2,3...)
AND customerId NOT IN (33,2323,34534...)
AND age IN (5, 7, 72)
Have (at least):
INDEX(cityId),
INDEX(age)
(Negated things are unlikely to be able to use an index.)
The query will use one of the indexes; having both will give the Optimizer a choice of which it thinks is better.
Or...
SELECT c.*
FROM customers AS c
JOIN cityEligible AS b ON b.city = c.city
JOIN customerEligibleAge AS ce ON c.age = ce.age
LEFT JOIN customerIdToBeExcluded AS ex ON c.customerId = ex.customerId
WHERE ex.customerId IS NULL
Suggested indexes (probably as PRIMARY KEY):
customers: (city)
customerEligibleAge: (age)
customerIdToBeExcluded: (customerId)
In order to discuss further, please provide SHOW CREATE TABLE for each table and EXPLAIN SELECT ... for any of the queries actually work.
If you use the database only that operation, I recommend to use the first solution. Also the first solution is very simple to deploy.
The second solution fills up with junk the DB.

mysql insert information from multiple rows from another table

I am using MySQL version 5.6.
I have a table event that takes two ids and a date, and a table student that contains a column id. I want to insert two ids when the name match (WHERE firstname =.., AND lastname=..,). However, I don't quite know how to take id from two rows in one insert command. Can any one help me please?
Thanks,
Paul
If you are trying to insert into a table, then you want to use insert. To get data from another table or query, you would want the insert . . . select form.
From what you say, this seems something like what you want:
insert into event(id1, id2, date)
select s1.id, s2.id, now()
from student s1 cross join
student s2
where s1.id <> s2.id and
s1.firstname = firstname and s1.lastname = lastname and
s2.firstname = firstname and s2.lastname = lastname;
It would return all pairs of students where the names match (but don't have the same id).

Access Query IIf Value in Values returned by another Query

I have a Query that looks up an Employee ID, Employee Name and Team Name from the current Staff Database. I have another Query that lists all unique values in Team Name. (Team Name is an Integer, and corresponds to Employee ID, also an Integer.)
Eg this is how teams are structured. Emp ID 100 belongs to Emp ID 10's team. 10 belongs to 5. 5 belongs to 1, etc.
EmpID = 100
TeamName = 10
EmpID = 10
TeamName = 5
EmpID = 5
TeamName = 1
What I am trying to do is return a fourth field, giving an asterisk, "*", when the Emp ID also appears in the Team Name query (Thus meaning they have a team/are a Manager).
I have a DCount that works, but it is slower than I'd like, and will only get slower as the Database grows, but it might serve to explain what I need.
Expr1: IIf(DCount("TeamName","jdbo_MostRecentEmpDataRemain","TeamName = " & [EmpID])>0,"*","")
jdbo_MostRecentEmpDataRemain is a Query that returns all data for staff that are active.
This will return an Asterisk if the EmpID has team members assigned to them, and nothing if they do not.
I'm wondering if this can be applied through queries to make it faster. Please let me know if you have any suggesstions.
I tried this: Expr2: IIf([EmpID] In ([qryListOfTeams].[TeamName]),"a","z")
but that returns lots of z's and then an a, as it seems to return a value for every value that is in the Team List. I want it to aggregate those and display an a if there is an a, otherwise a z. (Where in the original "*" is the a, and "" is the z)
Kind regards,
Jamie Warburton
How about:
SELECT * FROM TableOrQuery
LEFT JOIN (SELECT DISTINCT EmpID FROM Teams
WHERE EmpID In (SELECT TeamName FROM Teams)) As a
ON TableOrQuery.EmpID = a.EmpID
Derived tables are usually faster than subqueries.
EDIT re comment
Asterisk has a specific meaning, so while you can do this, I do not recommend it.
SELECT TableOrQuery.*, a.IsTeam FROM TableOrQuery
LEFT JOIN (SELECT DISTINCT EmpID, "*" As IsTeam FROM Teams
WHERE EmpID In (SELECT TeamName FROM Teams)) As a
ON TableOrQuery.EmpID = a.EmpID