How can I use a variable in a relational algebra query? - relational-database

I have the following table.
I would like to find the following in a query:
The sailor names for sailors who reserve ONLY the boats that Brown reserves (Meaning only Brown and Blake should show up, as they are the only ones solely reserving Boat 1 and Boat 4 in the Reservation table).
I have tried the following, and have even used a relational algebra calculator however I am stuck. I am able to get to the point where all rows in the table include the correct boats, however I don't know how to exclude the entries with extra boats on top of that. All help would be appreciated. Thanks.
X = π SN, BN (Reservation) ⨝ π SN, Name (Sailer)
Y = π SN, BN (Reservation) ⨝ π BN (Boat)
Z = X ⨝ Y
CONTAINING = π Name, SN, BN (Z) / π BN (σ Name = 'Brown' (Z)) ⨝ Z
LAST = CONTAINING - π SN, BN, Name (σ Name = 'Brown' (Z))
RESERV = γ Name; count(Name)->NUM_RESERV (CONTAINING)
π Name (σ NUM_RESERV = NUM_RESERV RESERV)
This produces:
Sailer.Name:
Smith
Blake
Brown

Here is the sketch of a solution:
let reserved-by-brown the table consisting of the BN of the boats reserved by Brown; this can be found by joining the three tables with a restriction on sailor name and a projection on BN.
Let sails the table obtained by the division of projection on SN and BN of Reservation by the table reserved-by-brown. This produces the SN of the sailors who have at least reserved all the boat reserved by Brown.
Let non-brown the table obtained with the difference from the projection of Boat on BN and reserved-by-brown: this contains all the BN of boat non reserved by Brown.
Let non-brown-reservation the join between non-brown and reservation on the attribute BN. This contains all the reservations without those of boats reserved by Brown.
Finally, compute the difference between sails and the projection on SN of the previous table non-brown-reservation. This will contain the desired result.

Related

Putting one line per name using SQL

I have this sql output that gives me different row for the same person based on their location. I wanted one line per person and three columns with a Y if they lived there.
Select name, Paris, London, NYC from location
Name Paris London NYC
John y
John y
John y
I want this
Name Paris London NYc
John y y y
you can use max function :
select name, max(paris), max(london), max(nyc) from location
group by name
SELECT name,
IF(SUM(IF(Paris='y',1,0)>0,'y','') as Paris,
IF(SUM(IF(London='y',1,0)>0,'y','') as London,
IF(SUM(IF(NYC='y',1,0)>0,'y','') as NYC
FROM location
GROUP BY name
Side-note, the database is not designed optimally! 3 tables with Name, Cities and Location with proper joins would be much more efficient.
Use Subselects like:
Select name,
(SELECT Paris FROM location WHERE name = a.name),
(SELECT London FROM location WHERE name = a.name)
FROM location a
This way you make a Select in an Select, and link the subselect to the name of the overlaying select.
Some of the other users told you to use aggregations.
In the most database systems an aggregation query is less efficient than a subquery, so you should use aggregations with care.

SQL query for extracting data from related tables

Although I found several similar problems but I couldn't apply them to resolve my issue.
Problem statement:- I have three MySql tables STUDENT,SUBJECT and STUDIES as described below:-
STUDENT-
rollno Name
X1 Alpha
X2 Beta
Y1 Zeta
X3 Omega
here the alphabet in each rollno corresponds to student in same batch/class. E.g students X1,X2 and X3 belong to same class whereas Y1 is that of a different one.
SUBJECT-
Code Title Credits
abc subject1 2
bcd subject2 4
gfp subject3 3
STUDIES-
rollno code
X1 abc
X1 bcd
X1 gfp
X2 bcd
X2 abc
Y1 gfp
X3 abc
I need help in framing mysql queries for:
a) displaying the credits undertaken by each student.
Like
Rollno Name Credits
X1 Alpha 9
X2 Beta 6
Y1 Zeta 3
X3 Omega 2
The best that I have come up is with this
select rollno,
(select sum(credits) from subject
where studies.code=subject.code)
from studies;
But what I get are the rollno and credits displayed individually for every subject a student studies.(I haven't been able to scale my query to get the name of student from the third table yet)
b) Finding out the subjects which have been taken by all the students of a class/batch.
In the given scenario the answer would be
Batch Subject Code Title
X abc subject1
I can extract out distinct batches by string processing but dont know how to proceed further from that point.
c) Being a MySql newbie, could you also point me out to some good web resource with practice problems for learning advanced queries like these. I have gone through a few of them on the last couple days but have not found them sufficient in developing concepts required to get through my queries.
EDIT: Sharing the CREATE queries for the tables:-
For SUBJECT:
CREATE TABLE IF NOT EXISTS subject (
code varchar(8) UNIQUE, title varchar(75) NOT NULL,
credits int, check (credits <5),PRIMARY KEY (code));
For STUDENT:
CREATE TABLE IF NOT EXISTS student (
rollno varchar(9) UNIQUE,name varchar(50));
For Studies:
CREATE TABLE IF NOT EXISTS studies (
rollno varchar(9) NOT NULL,code varchar(50) NOT NULL,
FOREIGN KEY(rollno) REFERENCES student(rollno));
Well, for your first query, you want to join across all three tables, looking for rollno, name, and credits. So at a first pass, you need to join like this:
SELECT s.rollno, s.name, sb.credits
FROM student s
INNER JOIN studies st
ON st.rollno = s.rollno
INNER JOIN subject sb
ON sb.code = st.code
This is part of the solution - it gives you the information you want, and now you just have to use an aggregate function to tally up the credits, using SUM and GROUP BY:
SELECT s.rollno, s.name, SUM(sb.credits) AS credits
FROM student s
INNER JOIN studies st
ON st.rollno = s.rollno
INNER JOIN subject sb
ON sb.code = st.code
GROUP BY s.rollno, s.name
The second part is tougher, and there are likely other (and better) ways to do this, but here's my approach:
SELECT q1.batch, q1.code, sb.title
FROM
(SELECT st.code, SUBSTR(st.rollno,1,1) batch,
COUNT(SUBSTR(st.rollno,1,1)) numb
FROM studies st
GROUP BY st.code, SUBSTR(st.rollno,1,1)) q1
INNER JOIN
(SELECT SUBSTR(s.rollno,1,1) batch,
COUNT(SUBSTR(s.rollno,1,1)) numb
FROM student s
GROUP BY SUBSTR(s.rollno,1,1)) q2
ON q1.batch = q2.batch AND q1.numb = q2.numb
INNER JOIN subject sb
ON q1.code = sb.code
Some explanation: the first sub-query (q1) counts the number of students from each batch in each subject. The output from that would be:
abc x 3
bcd x 2
gfp x 1
gfp y 1
The second subquery (q2) counts the number of students in each batch, with output:
x 3
y 1
By JOINing these two subqueries, we select only those subjects where the batch and the batch count are the same:
abc x 3
gfp y 1
Finally, JOIN on the subject table to get the subject title included (and set the starting SELECT statement to only select batch, code, and title), giving output:
x abc subj1
y gfp subj3
Note that the last row here (y - subj3) is valid, since every member of the 'y' batch (of which there is only one) is enrolled in course gfp.
As for recommended sites and resources - that's a bit outside the scope of SO. You can find lots of good online resources by Googling 'SQL tutorial' or 'SQL online courses'. Lots of good free stuff out there.

MYSQL How to input externally calculated value into row

I'm having some issues with this MySQL query. I've got two tables, one that has a list of all the "Leaders of the Opposition"(People elected into office) with the date that they were elected. And I've got another table of all the people they've been married to, and the year they got married in.
I'm trying to make a query that returns all the Leaders of the Opposition ordered by their appointment date with their current spouses name at the time and the date of their marriage.
Here is some practice data of just one leader, dates changed a bit to fit the sort of problem I'm trying to solve.
TABLE ONE:
Leader_of_Opposition------Date Elected
Beazley K C, 1996-03-19
Beazley K C, 2005-01-28
TABLE TWO:
Leader_of_Opposition----Spouses's Name----Year Married
Beazley K C, Mary Ciccarelli, 1974
Beazley K C, Susie Annus, 2004
-
And I'm trying to get it to something like this:
Leader_of_Opposition------Date Elected------Spouses's name--------Year Married
Beazley K C, 1996-03-19, Mary Ciccarelli, 1974
Beazley K C, 2005-01-28, Susie Annus, 2004
-
So far I've got the basics of:
SELECT opposition.leader_name, opposition.time_begin, opposition_marriage.spouse_name, opposition_marriage.year_married'
FROM opposition, opposition_marriage
AND opposition.leader_name=opposition_marriage.leader_name
ORDER BY opposition.time_begin
But it gives me results where the leaders are mentioned multiple times for each marriage. And I can't figure out the syntax to search the other table then place that value into the row.
Any help would be extremely appreciated, been banging my head up against this one for a while now.
Thanks in advance.
I think this is going to be easiest with correlated subqueries. Alas, though, your tables do not have unique identifiers for each row.
SELECT o.leader_name, o.time_begin,
(select om.spouse_name
from opposition_marriage om
where o.leader_name = om.leader_name and om.year_married <= year(o.date_elected)
order by om.year_married desc
limit 1
) as spouse_name,
(select om.year_married
from opposition_marriage om
where o.leader_name = om.leader_name and om.year_married <= year(o.date_elected)
order by om.year_married desc
limit 1
) as year_married
FROM opposition o
ORDER BY o.time_begin;
This handles as many marriages as you like.
Now some comments:
It seems really strange to have a table only of marriages for the opposition leaders and not for all politicians.
The granularity is at the level of a "year", so a leader married in the same year after s/he takes office counts as being married to that spouse.
You do not have a "marriage end date", so a divorced or widowed partner would be considered current until the next marriage.
As I mention in the beginning, you should have a unique identifier for each row.

Variance Dissimilarity in SQL with three table

I have three table:
rtgitems
rtgusers
POI
(the tables aren't complete for reasons of space).
I want to resolve this form:
where r_i,x is the value of column "voto" for the user "rater" i for the "item" x and avg_x is the average (the division from "totalrate" and "nrrates" -> totalrate/nrrates). |G| is given and isn't a trouble.
I want this table result:
Nome (from POI) | VD_x(G)
Tour Eiffel | 23
Arc | 18
...
I tried this for the firsts two table for to take the value for calculate the average (the third table I don't know how matching with the others):
SELECT totalrate, nrrates, voto FROM rtgitems INNER JOIN rtgusers ON rtgitems.item=rtgusers.item GROUP BY rater
but don't work.
Thanks for the help.
Just focus on the rtgusers table. If you want to bring in the names, that's fine. You can do it after the variance calculation (you seem to know what a join is). The first table seems superfluous to the problem.
You can calculate the variance by pre-calculating the summary values and then applying the formula. I think this is the basic logic that you want:
SELECT ru.item, (1.0 / max(rus.n)) * sum(power(ru.voto - avg_voto), 2)
FROM rtgusers ru join
(select ru.item, avg(voto * 1.0) as avg_voto, count(*) as n
from rtgusers ru
group by ru.item
) rus
on ru.item = rus.item
group by ru.item;

What happens when we theta join or cross 2 relations with common attributes?

Relation 1 (r1):
ID | Name
1 John
2 Doe
3 Foo
Relation 2 (r2):
ID | Name
4 Johnny
5 Doey
6 Fooey
What will r1 theta join(r1.ID = r2.ID) r2 result in?
What will r1 cross r2 result in?
I'm just asking whether the resulting relations should change the names of the attributes to something else because there are 2 of each.
In relational algebra, product (cross join) is usually understood to be a special case of natural join where the joined relations happen to have no attributes in common. So it doesn't make sense to say A x B if A and B have common attributes. If A and B have attributes in common then A x B either means A ⋈ B or it means a mistake has been made and your DBMS or interpreter probably ought to report an error.
Theta join is a shorthand for natural join followed by a restriction. It must be preceded by a rename of some attribute(s) if the attributes in the theta expression would otherwise have the same names.