[ Milan Andjelkovic @ 08.01.2006. 23:19 ] @
Naziv teme je verujem vrlo loš, ali neka moderator izmeni jer ja stvarno nisam uspeo da smislim nešto normalno :)

Treba mi 'algoritam' za rešavanje sledećeg tipa problema:

Baza:
+-----+----------+
| sid | meets_at |
+-----+----------+
| 1 | 09:00:00 |
| 2 | 14:00:00 |
| 6 | 14:00:00 |
| 7 | 10:00:00 |
| 9 | 14:00:00 |
| 14 | 14:00:00 |
| 22 | 10:00:00 |
| 22 | 14:00:00 |
| 23 | 15:00:00 |
| 24 | 09:00:00 |
| 29 | 14:00:00 |
| 30 | 14:00:00 |
| 39 | 14:00:00 |
| 39 | 17:00:00 |
| 41 | 14:00:00 |
| 43 | 14:00:00 |
| 48 | 10:00:00 |
| 52 | 15:00:00 |
+-----+----------+

Kao što se da primetiti, sid nije unikatan. Ono što treba da izvučem jesu svi sid-ovi koji u odgovarajućim meets_at poljima imaju makar jednom vrednost veću od 12:00:00 i makar jednom vrednost manju od 12:00:00. U ovom konkretnom slučaju, traženi rezultat je samo sid 22 (sid 39 u oba reda u meets_at polju ima vrednosti veće od 12:00:00, dok sid 22 ima jednom veću, a jednom manju vrednost, što je i traženo).

Ja sam ovo uspeo da rešim tako što sam napravio jednu tabelu sa svim redovima u kojima je meets_at manje od 12:00:00 i jos jednu gde je meets_at veće od 12:00:00, pa sam zatim ukombinovao te dve tabele, odnosno izvukao sid koji se pominje u obe.
Ipak, ne mogu da se otmem utisku da to može mnogo elegantnije i praktičnije da se reši (već u narednim problemima istog tipa sa kojima se srećem ovaj algoritam postaje vrlo nezgodan za implementaciju)?

OS: Windows XP
Server version: 5.0.18-nt
Protocol version: 10
[ Dejan Topalovic @ 09.01.2006. 09:23 ] @
Code:

SELECT sid
FROM tabela
WHERE sid IN
     (
     SELECT sid
     FROM tabela
     WHERE meets_at > '12:00:00'
     )
AND sid IN
     (
     SELECT sid
     FROM tabela
     WHERE meets_at < '12:00:00'
     )
ORDER BY sid;
Napisano iz glave; provjeri da li radi...
[ Milan Andjelkovic @ 09.01.2006. 12:40 ] @
Da, to je otprilike i rešenje do koga sam ja došao. Činilo mi se da postoji neki drugi način da se to odradi, ali to izgleda nije slučaj.

Hvala
[ jablan @ 09.01.2006. 12:49 ] @
Eventualno
Code:

select distinct tabelaam.sid
from tabela tabelaam
inner join tabela tabelapm on tabelaam.sid = tabelapm.sid
where 
tabelaam.meets_at < '12:00:00'
and tabelapm.meets_at > '12:00:00'
[ Milan Andjelkovic @ 11.01.2006. 10:36 ] @
Ok, sa ovim prethodnim sam se snašao. Ali evo sad situacije gde umesto dva uslova (pre 12h i posle 12h) ima praktično n uslova:
mysql> SELECT * FROM rooms;
+------------+
| room |
+------------+
| Large Hall |
| A5 |
| Small Hall |
+------------+
3 rows in set (0.00 sec)

mysql> SELECT * FROM combs;
+------------+------------+
| insname | room |
+------------+------------+
| Williamson | Large Hall |
| Weasley | Small Hall |
| Weasley | A5 |
| Weasley | Large Hall |
| Potter | A5 |
| Johnson | Small Hall |
| Johnson | A5 |
| Daniels | A5 |
| Daniels | Small Hall |
| Daniels | Large Hall |
| Wilson | Large Hall |
| Wilson | A5 |
| Smith | Large Hall |
| Wesson | A5 |
+------------+------------+
14 rows in set (0.00 sec)

Sad treba da izvučem imena (insname) iz combs, koja su vezana za sve sobe (room) iz rooms (traženi rezultat u ovom slučaju je Weasley i Daniels). U ovom slučaju ima tri sobe, i ja bih to mogao da rešim na već opisani način, ali šta ako soba ima mnogo? Bilo bi vrlo nepraktično praviti takav kveri za recimo 30 soba.

Pokušao sam to da odradim tako što poredim broj redova u rooms i broj pojavljivanja svakog imena u combs, ali izgleda da to nisam odradio kako treba:
mysql> SELECT insname FROM combs,rooms GROUP BY insname HAVING COUNT(insname)=COUNT(rooms.room);
+------------+
| insname |
+------------+
| Daniels |
| Johnson |
| Potter |
| Smith |
| Weasley |
| Wesson |
| Williamson |
| Wilson |
+------------+
8 rows in set (0.00 sec)

Ovo mi se čini kao najbolje rešenje, samo što ga nisam implementirao kako treba. Mučim se sa ovim već neko vreme, pa bi bilo lepo ako bi neko mogao da mi pomogne?
[ jablan @ 11.01.2006. 10:54 ] @
Ne znam kako MySQL stoji sa podupitima, na MSSQLu bi bilo ovako nešto:
Code:

SELECT insname
FROM combs
GROUP BY insname
HAVING COUNT(*) = (SELECT COUNT(*) FROM rooms)
[ Milan Andjelkovic @ 11.01.2006. 11:03 ] @
Veliko hvala!

Taj SELECT u okviru HAVING mi je nedostajao (umesto samo COUNT(rooms.room)). Čini mi se da mysql dobro stoji sa podupitima od verzije 5.0, koju ja i koristim.

Hvala još jednom...