Hallo allemaal,
Ik ben bezig met een school rooster database, bestaande uit meerdere tabellen, maar de focus ligt bij mijn vraag op twee tabellen hiervan. Ik wil graag dat de uitkomst van mijn query alle lege lokalen weergeeft op een bepaald lesuur.
In de eerste tabel, tabel1, staan de lesuren, maandag het eerste als ma1, woensdag 7e als wo7, enzovoort. Ook staat er een key in voor elk lesuur.
In de tweede tabel, tabel2, staan de lessen. Hierin staat lokaal, docent, vak, lesuur, groep, en les id.
Zelf kwam ik niet verder dan een lijst krijgen van alle lokalen (select lokaal from tabel2 group by lokaal order by lokaal). Hoe pas ik deze query aan (subquery??) zodat de output alle lege lokalen op een bepaald lesuur zijn?
Iets meer info zal nodig zijn denk ik.
vb: Hoe is lesuur opgebouwd.
eventueel een volledige structuur van beide tabellen.
show create table tablename 


Jan
CREATE TABLE `lessen` (
 `id_lessen` int(4) NOT NULL AUTO_INCREMENT,
 `groep` varchar(6) DEFAULT NULL,
 `lesuur` varchar(3) DEFAULT NULL,
 `vak` varchar(3) DEFAULT NULL,
 `docent` varchar(3) DEFAULT NULL,
 `lokaal` varchar(3) DEFAULT NULL,
 PRIMARY KEY (`id_lessen`)
) ENGINE=MyISAM AUTO_INCREMENT=1581 DEFAULT CHARSET=latin



CREATE TABLE `lesuurnr` (
 `lesuurnr` int(3) NOT NULL,
 `lesuur` varchar(3) NOT NULL,
 PRIMARY KEY (`lesuurnr`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Ik zou ook een lokalen-tabel verwachten? Indien een lokaal altijd beschikbaar is dan kun je dit nooit afleiden uit bovenstaande tabellen, daar het alleen bezette tijden/locaties betreft en dat lokaal zal daar dan dus nooit in voorkomen.

In een "lege lokalen query" zouden de (alle aanwezige) lokalen een goed uitgangspunt vormen denk ik. Je hebt die informatie namelijk nodig om de "ruimte van beschikbare lokalen op te spannen".
Nope die is er geen, de andere twee tabellen zijn gegevens over de klas en over leerlingen. Het is niet de eerste keer dat deze opdracht gegeven is, dus het zou te doen moeten zijn met een (sub)query. Misschien trouwens met een beetje php? Ik heb namelijk echt geen idee ik loop helemaal vast
Ik denk dat een lokalen-tabel zeker niet mag ontbreken. Wat is er mis mee op die op te zetten?
Dat gaat tegen de opdracht in.. Dat is dus het lastige. Maar anders bedoel je dus een tabel met alleen alle lokalen en een id voor de lokalen?
Lijkt mij handig, je kunt dan namelijk een soort van (denkbeeldige) matrix maken met op de ene as de lokalen en op de andere as de lesuurnummers die je vervolgens loslaat op de lessen. De "gaten" in deze matrix vormen dan de lokalen die op een bepaald tijdstip beschikbaar zijn.
je hebt vrij zeker een lokalen-tabel nodig.

Je zou uit de tabel Lessen weliswaar alle lokalen kunnen opzoeken, maar stel in lokaal 99 is nooit les.
Dan staat dat lokaal niet in Lessen, en zou je die dus ook niet als "vrij" kunnen vinden.

Dat betekent ook dat je aan het begin van het jaar (nog geen lessen in je rooster) sowieso geen enkel vrij lokaal gaat vinden.


Ik zou in Lessen trouwens ook geen kolom Lesuur varchar(3) verwachten, maar een Lesuurnr int()

net als voor lokaal, docent etc.
Dus `lessen` koppelt lesinformatie met de les-uren in de tabel `lesuurnr` via de gedeelde kolommen `lessen`.`lesuur` en `lesuurnr`.`lesuur`. En je wilt een lijstje hebben van alle rijen in `lesuurnr` die nog niet gekoppeld zijn, ofwel die nog vrij zijn.

Dan zou de volgende query voldoende moeten zijn:

SELECT 
  `lesuurnr`.`lesuurnr`,
  `lesuurnr`.`lesuur`
FROM `lesuurnr`
WHERE `lesuurnr`.`lesuur` NOT IN (
  SELECT `lessen`.`lesuur`
  FROM `lessen`);
Of je maakt van de lesuren en lokalen een cartesisch product (CROSS JOIN) en vergelijkt dit dan met lesuren.
Hiervoor heb je dan een lokalen-tabel nodig, maar die is sowieso zinnig om te hebben zoals @Ivo en ik al aangaven.

Structuur
CREATE TABLE locations (
loc_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
loc_description  VARCHAR(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE timeslots (
tsl_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
tsl_description  VARCHAR(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE lessons (
les_tsl_id INT(10) UNSIGNED NOT NULL,
les_loc_id INT(10) UNSIGNED NOT NULL,
les_description VARCHAR(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE lessons ADD CONSTRAINT id_lessons PRIMARY KEY (les_tsl_id, les_loc_id);
ALTER TABLE lessons ADD FOREIGN KEY (les_tsl_id) REFERENCES timeslots(tsl_id);
ALTER TABLE lessons ADD FOREIGN KEY (les_loc_id) REFERENCES locations(loc_id);


Data
INSERT INTO locations (loc_description) VALUES ('lokaal A'), ('lokaal B'), ('lokaal C');
INSERT INTO timeslots (tsl_description) VALUES ('ma1'), ('ma2'), ('ma3');
INSERT INTO lessons (les_tsl_id, les_loc_id, les_description) VALUES (1,1,'Frans'), (2,1,'Nederlands'), (2,2,'Duits'), (3,3,'Engels');


Query
SELECT t.tsl_description, l.loc_description
FROM locations l
CROSS JOIN timeslots t
WHERE NOT EXISTS (
	SELECT 1
	FROM lessons
	WHERE les_tsl_id = t.tsl_id
	AND les_loc_id = l.loc_id
);


Levert
+-----------------+-----------------+
| tsl_description | loc_description |
+-----------------+-----------------+
| ma1             | lokaal B        |
| ma1             | lokaal C        |
| ma2             | lokaal C        |
| ma3             | lokaal A        |
| ma3             | lokaal B        |
+-----------------+-----------------+


Of als je dit voor de leesbaarheid wilt groeperen op lokaal
SELECT l.loc_description AS locatie, GROUP_CONCAT(t.tsl_description) AS vrij
FROM locations l
CROSS JOIN timeslots t
WHERE NOT EXISTS (
	SELECT 1
	FROM lessons
	WHERE les_tsl_id = t.tsl_id
	AND les_loc_id = l.loc_id
)
GROUP BY l.loc_id;


Levert
+----------+---------+
| locatie  | vrij    |
+----------+---------+
| lokaal A | ma3     |
| lokaal B | ma1,ma3 |
| lokaal C | ma1,ma2 |
+----------+---------+

Reageren