How to select just parent and not inherit values - sql

I have 3 tables. Game, FinalGame which extends Game and Participant who has list of game and list of FinalGame. Now I have problem. How to select just game and not finalGame. How to select Participant with just game and not finalGame.
In first option I tried:
select * from game g where {g.ID not in (select pl.game_id from PLAY_OFF_TABLE pl) }
but I am not sure if it is right.
In second option I tried;
select * from participant p left join game g1 on p.ID = g1.HOME_PARTICIPANT_ID
but this select all games including final. I have no idea how I can exclude final game
CREATE TABLE IF NOT EXISTS `GAME` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`HOME_PARTICIPANT_ID` int(11) DEFAULT NULL,
`AWAY_PARTICIPANT_ID` int(11) DEFAULT NULL,
`STATUS` enum('WIN','LOSE','DRAW') DEFAULT NULL,
`RESULT` varchar(50) DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `HOME_PARTICIPANT_ID` (`HOME_PARTICIPANT_ID`),
KEY `AWAY_PARTICIPANT_ID` (`AWAY_PARTICIPANT_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;
CREATE TABLE IF NOT EXISTS `PLAY_OFF_GAME` (
`GAME_ID` int(11) NOT NULL,
`GROUP_ID` int(11) NOT NULL,
`POSITION` int(11) NOT NULL,
PRIMARY KEY (`GAME_ID`),
KEY `GROUP_ID` (`GROUP_ID`),
KEY `POSITION` (`POSITION`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `PARTICIPANT` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
...
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;
UPDATE:
select * from PARTICIPANT p left join GAME g1 on p.ID = g1.HOME_PARTICIPANT_ID join PLAY_OFF_GAME pl on g1.id = pl.GAME_ID where p.group_id = 441 and pl.GAME_ID is null
retun 0 rows
select * from PARTICIPANT p left join GAME g1 on p.ID = g1.HOME_PARTICIPANT_ID left join PLAY_OFF_GAME pl on g1.id = pl.GAME_ID where p.group_id = 441 and pl.GAME_ID is null
return 5
select * from PARTICIPANT p left join GAME g1 on p.ID = g1.HOME_PARTICIPANT_ID left join PLAY_OFF_GAME pl on g1.id = pl.GAME_ID where p.group_id = 441
return all participant 8 but also final game which I want to exclude

Your first query would select GAME rows that do not have a corresponding PLAY_OFF_GAME, but a join is probably much quicker:
SELECT *
FROM GAME g
LEFT JOIN PLAY_OFF_GAME pog ON g.ID=pog.GAME_ID
WHERE pog.GAME_ID IS NULL;
For the second question, you can do the same trick:
SELECT * FROM (
(SELECT p1.*, g.ID
FROM PARTIPANT p1
LEFT JOIN GAME g1 ON p1.ID=g1.HOME_PARTICIPANT_ID
LEFT JOIN PLAY_OFF_GAME pog1 ON g1.ID=pog1.GAME_ID
WHERE pog1.GAME_ID IS NULL)
UNION
(SELECT p2.*, NULL
FROM PARTICIPANT p2
JOIN GAME g2 ON p2.ID=g2.HOME_PARTICIPANT_ID
JOIN PLAY_OFF_GAME pog2 ON g2.ID=pog2.GAME_ID)) AS tmp;
Query may have typos. First selects Particpants in a game, or in no game, but it's excluding the participants only in final games. The second select fills those back in, ignoring the game.
Also:
To select all participants, and not just 'home' participants, not in a game or in a non-playoff game, add OR p.ID=g.AWAY_PARTICIPANT_ID to the ON clause. (I'm following your example, but the description seems to be at odds.
Should there be a foreign key constraint on PLAY_OFF_GAME? E.g., CONSTRAINT play_off_game_fk FOREIGN KEY (GAME_ID) REFERENCES GAME (ID)?

Related

Using inner join as ALIASES with multiple tables

I have these tables below:
create table student(
studentName varchar (40) not null,
studentRollNo varchar (30) primary key, -- also acts as username
studentPassword varchar(30) NOT NULL,
studentGender varchar(7) default NULL
);
create table supervisors(
supervisorID varchar(30) foreign key references Faculty(facultyID) unique,
sWorkLoad int default null,
CHECK (sWorkLoad<=6 and sWorkLoad>=0)
);
create table co_supervisors(
co_supervisorID varchar(30) foreign key references Faculty(facultyID) unique,
csWorkLoad int default null,
CHECK (csWorkLoad<=6 and csWorkLoad>=0)
);
create table studentGroup(
groupID int IDENTITY(1,1) primary key ,
Member1rollNo varchar(30) foreign key references student(studentRollNo) default NULL, -- member 1
Member2rollNo varchar(30) foreign key references student(studentRollNo) default NULL, -- member 2
Member3rollNo varchar(30) foreign key references student(studentRollNo) default NULL, -- member 3
supervID varchar(30) foreign key references supervisors(supervisorID),
co_supervID varchar(30) foreign key references co_supervisors(co_supervisorID) default NULL,
projectTitle varchar(100) not null,
projectDetails varchar (500) default NULL
);
create table FYP1(
groupID int foreign key references studentGroup(groupID),
);
I want to display student details who are registered in FYP1.
with their supervisors, co_supervisors,and project title.
But I I'm not able to do so,
What I have done so far is this.
select sg.Member1rollNo,S.studentName,Member2rollNo,S.studentName,sg.Member3rollNo,sg.supervID,sg.projectTitle
FROM student S
inner join studentGroup SG ON S.studentRollNo = SG.Member1rollNo
OR some random tries like this
-- Faculty.facultyName
SELECT FYP1.groupID, studentGroup.Member1rollNo,student.studentName as student1, studentGroup.Member2rollNo,student.studentName as student2,studentGroup.projectTitle
FROM FYP1 as FYP1_Students
INNER JOIN studentGroup ON (studentGroup.groupID = FYP1_Students.groupID)
INNER JOIN supervisors ON (studentGroup.supervID = supervisors.supervisorID)
INNER JOIN student ON (student1.studentRollNo = studentGroup.Member1rollNo)
INNER JOIN student ON (student.studentRollNo = studentGroup.Member2rollNo)
Output or first query is this (example):
'i19-0434' 'Sourav Malani' 'i19-0498' 'Sourav Malani' NULL 'urooj.ghani' 'Indoor Navigation'
'i19-0466' 'Aftab Ali' 'i19-0528' 'Aftab Ali' NULL 'urooj.ghani' 'AI based Physics exp.'
I want output to be like:
'i19-0434' 'Sourav Malani' 'i19-0498' 'Student2 Name' NULL 'urooj.ghani' 'Indoor Navigation'
'i19-0466' 'Aftab Ali' 'i19-0528' '<student2Name>' NULL 'urooj.ghani' 'AI based Physics exp.'
Sample Data
Thanks to #Hana, I solved the problem.
Here's the solution:
SELECT SG.groupID,
SG.Member1rollNo,S1.studentName as 'student1 Name',
SG.Member2rollNo, S2.studentName as 'student2 Name',
SG.Member3rollNo, S3.studentName as 'Studen3 Name',
SG.supervID, SN.facultyName as 'Supervisor Name',
SG.co_supervID, CSN.facultyName as 'Co_Supervisor',
SG.projectTitle as 'Project Title',
SG.projectDetails as 'Project Desc.'
FROM FYP1 FYP1
LEFT OUTER JOIN studentGroup SG ON FYP1.groupID = SG.groupID
LEFT OUTER JOIN supervisors SV ON SG.supervID = SV.supervisorID
LEFT OUTER JOIN Faculty SN ON SG.supervID= SN.facultyID
LEFT OUTER JOIN Faculty CSN ON SG.co_supervID= CSN.facultyID
LEFT OUTER JOIN student S1 ON SG.Member1rollNo = S1.studentRollNo
LEFT OUTER JOIN student S2 ON SG.Member2rollNo = S2.studentRollNo
LEFT OUTER JOIN student S3 ON SG.Member3rollNo = S3.studentRollNo
Is this what you are looking for?
SELECT SG.groupID, SV.supervisorID, CSV.co_supervisorID, S1.studentName, S2.studentName, S3.studentName
FROM FYP1 FYP1
INNER JOIN studentGroup SG ON FYP1.groupID = SG.groupID
INNER JOIN supervisors SV ON SG.supervID = SV.supervisorID
INNER JOIN co_supervisors CSV ON SG.co_supervID = CSV.co_supervisorID
INNER JOIN student S1 ON SG.Member1rollNo = S1.studentRollNo
INNER JOIN student S2 ON SG.Member1rollNo = S2.studentRollNo
INNER JOIN student S3 ON SG.Member1rollNo = S3.studentRollNo

Multiple selects on joined tables with group by?

I have three tables with the structures outlined below:
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(255) UNIQUE
);
CREATE TABLE posts (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT REFERENCES users(id) NOT NULL,
category BIGINT REFERENCES categories(id) NOT NULL,
text TEXT NOT NULL
);
CREATE TABLE posts_votes (
user_id BIGINT REFERENCES users(id) NOT NULL,
post_id BIGINT REFERENCES posts(id) NOT NULL
value SMALLINT NOT NULL,
PRIMARY KEY(user_id, post_id)
);
I was able to compose a query that gets each post with its user and its total value using the below query:
SELECT p.id, p.text, u.username, COALESCE(SUM(v.value), 0) AS vote_value
FROM posts p
LEFT JOIN posts_votes v ON p.id=t.post_id
JOIN users u ON p.user_id=u.id
WHERE posts.category=1337
GROUP BY p.id, p.text, u.username
But now I want to also return a column that returns the result of SELECT COALESCE((SELECT value FROM posts_votes WHERE user_id=1234 AND post_id=n), 0) for each post_id n in the above query. What would be the best way to do this?
I think an additional LEFT JOIN is a reasonable approach:
SELECT p.id, p.text, u.username, COALESCE(SUM(v.value), 0) AS vote_value,
COALESCE(pv.value, 0)
FROM posts p JOIN
users u
ON p.user_id=u.id LEFT JOIN
topics_votes v
ON p.id = t.post_id LEFT JOIN
post_votes pv
ON pv.user_id = 1234 AND pv.post_id = p.id
WHERE p.category = 1337
GROUP BY p.id, p.text, u.username, pv.value;

SQLite3 INNER JOIN with 3 tables

I'm trying to select from 3 tables with an INNER JOIN:
The tables:
CREATE TABLE tracks (
'track_id' INTEGER PRIMARY KEY NOT NULL,
'name' TEXT NOT NULL,
'length' REAL DEFAULT '0.00',
'city' TEXT
);
CREATE TABLE heats (
'heat_id' INTEGER PRIMARY KEY NOT NULL,
'track_id' INTEGER UNSIGNED NOT NULL,
'heat_pos' INTEGER UNSIGNED NOT NULL,
'day_pos' INTEGER UNSIGNED NOT NULL,
'type' TEXT NOT NULL DEFAULT 'training',
'average' REAL,
'date' TEXT,
'comment' TEXT,
FOREIGN KEY ('track_id') REFERENCES tracks ('track_id')
);
CREATE TABLE laps (
'lap_id' INTEGER PRIMARY KEY NOT NULL,
'heat_id' INTEGER UNSIGNED NOT NULL,
'laptime' REAL UNSIGNED NOT NULL,
FOREIGN KEY ('heat_id') REFERENCES heats ('heat_id')
);
When selecting information from 2 tables (laps and heats) it works like I expected:
select
laps.lap_id,
laps.laptime,
heats.heat_pos
from laps
inner join heats on laps.heat_id = heats.heat_id;
But now I want to select the corresponding tracknames from the track table:
select
laps.lap_id,
laps.laptime,
heats.heat_pos,
tracks.name
from laps, tracks, heats
inner join heats on laps.heat_id = heats.heat_id and
inner join heats on tracks.track_id = heats.track_id;
This gives me the following error:
ambiguous column name: heats.heat_pos
I'm completely lost, but I have a feeling it's just a small mistake.
Anyone knows what I'm doing wrong?
select
laps.lap_id,
laps.laptime,
heats.heat_pos,
tracks.name
from laps
inner join heats on laps.heat_id = heats.heat_id
inner join tracks on tracks.track_id = heats.track_id;
select
laps.lap_id,
laps.laptime,
heats.heat_pos,
tracks.name
from laps
inner join heats on laps.heat_id = heats.heat_id
inner join heats on tracks.track_id = heats.track_id
ORDER BY laps.lap_id

Help with complex join conditions

I have the following mysql table schema:
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
--
-- Database: `network`
--
-- --------------------------------------------------------
--
-- Table structure for table `contexts`
--
CREATE TABLE IF NOT EXISTS `contexts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`keyword` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
-- --------------------------------------------------------
--
-- Table structure for table `neurons`
--
CREATE TABLE IF NOT EXISTS `neurons` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
-- --------------------------------------------------------
--
-- Table structure for table `synapses`
--
CREATE TABLE IF NOT EXISTS `synapses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`n1_id` int(11) NOT NULL,
`n2_id` int(11) NOT NULL,
`context_id` int(11) NOT NULL,
`strength` double NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
What SQL can I write to get all Neurons associated with a specified context along with the sum of the strength column for the synapses associated with each neuron?
I'm using the following query, which returns the sum of the strength of the synapses associated with one neuron. I need to get information for all of the neurons:
/* This query finds how strongly the neuron with id 1 is connected to the context with keyword ice cream*/
SELECT SUM(strength) AS Strength FROM
synapses
JOIN contexts AS Context ON synapses.context_id = Context.id
JOIN neurons AS Neuron ON Neuron.id = synapses.n1_id OR Neuron.id = synapses.n2_id
WHERE Neuron.id = 1 AND Context.keyword = 'ice cream'
For example, that query returns one row, where Strength is 2. Ideally, I could have one column for the neurons.id, one for neurons.name, and one for SUM(synapses.strength) with one record for each distinct neuron.
Use:
SELECT DISTINCT
n.*,
COALESCE(x.strength, 0) AS strength
FROM NEURONS n
JOIN SYNAPSES s ON n.id IN (s.n1_id, s.n2_id)
JOIN CONTEXTS c ON c.id = s.context_id
LEFT JOIN (SELECT c.id AS c_id,
n.id AS n_id,
SUM(strength) AS Strength
FROM SYNAPSES s
JOIN CONTEXTS c ON c.id = s.context_id
JOIN NEURONS n ON n.id IN (s.n1_id, s.n2_id)
GROUP BY c.id, n.id) x ON x.c_id = c.id
AND x.n_id = n.id
Does this do what you want?
SELECT contexts.keyword, neurons.id, neurons.name, SUM(synapses.strength)
FROM neurons
INNER JOIN synapses ON neurons.id = synapses.n1_id OR neurons.id = synapses.n2_id
INNER JOIN contexts ON synapses.context_id = contexts.id
GROUP BY contexts.keyword, neurons.id, neurons.name

Problem selecting the latest record in JOIN

These are my 2 tables:
CREATE TABLE `documents` (
`Document_ID` int(10) NOT NULL auto_increment,
`Document_FolderID` int(10) NOT NULL,
`Document_Name` varchar(150) NOT NULL,
PRIMARY KEY (`Document_ID`),
KEY `Document_FolderID` (`Document_FolderID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=331 ;
CREATE TABLE `files` (
`File_ID` int(10) NOT NULL auto_increment,
`File_DocumentID` int(10) NOT NULL,
`File_Name` varchar(255) NOT NULL,
PRIMARY KEY (`File_ID`),
KEY `File_DocumentID` (`File_DocumentID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=333 ;
There can be multiple files to 1 document. I am trying to SELECT all of the documents with a JOIN on the files table but I only want 1 file record which is the latest one.
Here is my query I have come up with that doesn't quite work, can anyone suggest the right way?
SELECT `documents`.*
FROM `documents`
INNER JOIN (
SELECT MAX(`File_ID`), *
FROM `files`
WHERE `File_DocumentID` = `documents`.`Document_ID`
GROUP BY `File_ID` ) AS `file1`
ON `documents`.`Document_ID` = `file1`.`File_DocumentID`
WHERE `documents`.`Document_FolderID` = 94
ORDER BY `documents`.`Document_Name`
*edit: the error is Unknown column 'documents.Document_ID' in 'where clause'
Use:
SELECT d.*, f.*
FROM DOCUMENTS d
JOIN FILES f ON f.file_document_id = d.document_id
JOIN (SELECT t.file_document_id,
MAX(t.file_id) AS max_file_id
FROM FILES t
GROUP BY t.file_document_id) x ON x.file_document_id = f.file_document_id
AND x.max_file_id = f.file_id
The derived table/inline view called "x" is a join to the same table, all it does is tweak the records coming from the FILES table to be the highest per file_document_id...
Don't group by file_id, but by File_documentid.
I think I see what's wrong... You have GROUP BY File_ID, but I guess you really want GROUP BY File_DocumentID instead.