# Mir raucht der Kopf!



## Yitu (19. Sep 2014)

Ich kriege keine WHERE Klausel in meine Query zusammen um folgendes Problem zu lösen.

( Datumfelder in DATETIME ( stud_von / stud_bis ) )

Schüler A registriert seit 2010-xx-xx bis 2014-xx-xx
Schüler B registriert seit 2008-xx-xx bis 2010-xx-xx
Schüler C registriert seit 2011-xx-xx bis 2013-xx-xx
Schüler D registriert seit 2009-xx-xx bis 2014-xx-xx

Zeitraum ist z.B. $von = 2012-01-01 $bis = 2013-01-01

ich brauche alle Schüler die im Zeitraum registriert sind/waren


```
SELECT 
               bla bla bla
WHERE 
               (
                              ( '$von' BETWEEN stud_von AND stud_bis OR '$von' <= stud_von )
                              AND
                              ( '$bis' BETWEEN stud_von AND stud_bis OR '$bis' >= stud_bis )
                              
               )
```

bevor ich jetzt mit ANDs und ORs um mich schmeisse, dachte ich frag mal nach ob jemand was eleganters hat. ;(


----------



## taro (19. Sep 2014)

Das sollte eigentlich so reichen:


```
SELECT ....

WHERE '$von' >= stud_bis  AND '$bis' <= stud_von
```

'$von' >= stud_bis
schmeißt alle raus, die bis zu dem Startzeitpunkt die "registrierung" beendet haben

'$bis' <= stud_von
schmeißt alle raus, die sich danach registriert haben

bleiben also nur nur die, die in dem (Teil-)Zeitraum registriert waren

EDIT: Nachträglich kleine Verwirrung meinerseits korrigiert


----------



## Joose (19. Sep 2014)

Und abgesehen davon wäre ein anderer Titel für dieses Thema angebrachter.

Schön das dir der Kopf raucht, kannst auch im Beitrag schreiben. Dass hat aber im Titel nichts zu suchen!


----------



## Yitu (19. Sep 2014)

taro hat gesagt.:


> ...



ich probiere es mal aus, danke.

Edit:
geht leider nicht.


```
CREATE TABLE IF NOT EXISTS `studenten` (
  `id_student` int(6) NOT NULL AUTO_INCREMENT,
  `stud_vorname` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `stud_nachname` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `stud_von` datetime NOT NULL,
  `stud_bis` datetime DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id_student`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 COLLATE=latin1_german2_ci AUTO_INCREMENT=8 ;

INSERT INTO `studenten` (`id_student`, `stud_vorname`, `stud_nachname`, `stud_von`, `stud_bis`) VALUES
(1, 'Anna', 'Clarol', '2008-04-09 00:00:00', '2011-05-24 00:00:00'),
(2, 'Peter', 'Karremann', '2010-02-04 00:00:00', '0000-00-00 00:00:00'),
(3, 'Karin', 'Berghammer', '2012-01-22 00:00:00', '2014-06-06 00:00:00'),
(4, 'Ingo', 'Loger', '2014-05-30 00:00:00', '0000-00-00 00:00:00'),
(5, 'Holger', 'Niemitz', '2007-03-24 00:00:00', '2009-09-09 00:00:00'),
(6, 'Sabine', 'Türk', '2011-08-01 00:00:00', '0000-00-00 00:00:00'),
(7, 'Nana', 'Jemelin', '2011-01-01 00:00:00', '2011-03-03 00:00:00');
```


```
WHERE '2011-01-01' >= stud_bis  AND '2012-01-01' <= stud_von
```

Sollte...

Anna Clarol
Peter Karremann
Sabine Türk
Nana Jemelin

raushauen, da alle im Zeitraum vom 01.01.2011 bis 01.01.2012 registriert sind.


----------



## fLooojava (19. Sep 2014)

_( Datumfelder in DATETIME ( stud_von / stud_bis ) )

Schüler A registriert seit 2010-xx-xx bis 2014-xx-xx
Schüler B registriert seit 2008-xx-xx bis 2010-xx-xx
Schüler C registriert seit 2011-xx-xx bis 2013-xx-xx
Schüler D registriert seit 2009-xx-xx bis 2014-xx-xx_

_$x = '2011-01-01';
$y = '2012-01-01';
SELECT FROM ...
WHERE  $x >= stud_von AND stud_bis <= $y_

*$x >= stud_von: Alle Studenten/Schüler die sich nach 2011-01-01 registriert haben 

EDIT: <- die Aussage stimmt nicht, deshalb ist die Abfrage falsch, sry^^

stud_bis <= $y: Alle Studenten/Schüler die sich vor 2012-01-01 registriert haben.
-> Schnittpunkt: Zeitraum zwischen $x und $y *

sollte funktionieren, wie siehts aus?


----------



## Yitu (19. Sep 2014)

fLooojava hat gesagt.:


> sollte funktionieren, wie siehts aus?



Nah dran. 


```
SELECT * FROM `studenten`WHERE '2011-01-01' >= stud_von AND stud_bis <= '2012-01-01'
```

SQL-Ausgabe

```
1     Anna     Clarol              2008-04-09 00:00:00     2011-05-24 00:00:00
2     Peter     Karremann     2010-02-04 00:00:00     0000-00-00 00:00:00
5     Holger   Niemitz          2007-03-24 00:00:00     2009-09-09 00:00:00
7     Nana     Jemelin          2011-01-01 00:00:00     2011-03-03 00:00:00
```

Holger 	Niemitz ist nicht im Zeitraum.


----------



## JavaMeister (19. Sep 2014)

Was wäre deine Idee das zu korrigieren? - Oder endet deine Idee das einfach ins Forum zu stellen? Ich mein eine einfachere Abfrage gibt es kaum. Willst du alle SQLs hier reinstellen unter einem ähnlich schlecht gewählten Titel?


----------



## Joose (19. Sep 2014)

Einfach mal mitdenken:

Du hast den Zeitraum X bis Y und willst alle haben die während dieses Zeitraumes registriert waren.

Sprich du musst alle finden die sich vor und in diesem Zeitraum registriert haben "stud_von" <= "bis Y"
Sprich du musst alle finden die sich während und nach diesem Zeitraum abgemeldet haben "von X" <= "stud_bis"


----------



## fLooojava (19. Sep 2014)

Joose hat wiedermal Recht, aber n kleinen Denkfehler hast glaub ich noch, oder? 
Meine Abfrage oben ist natürlich schrott. 

$x ### stud_von ( startpunkt )   ###  stud_bis (endpunkt)  ###         $y

Somit muss stud_von größer bzw. gleich sein wie $x und stud_bis kleiner bzw. gleich wie $y.
d.h: $x <= stud_von AND stud_bis <= $y

Dann haben wir hier alle, die sich in diesem Zeitpunkt registriert haben, jedoch noch nicht die, die sich davor registriert haben und immer noch registriert sind.


----------



## Yitu (19. Sep 2014)

Joose hat gesagt.:


> Einfach mal mitdenken:
> 
> Du hast den Zeitraum X bis Y und willst alle haben die während dieses Zeitraumes registriert waren.
> 
> ...



geht auch nicht

```
WHERE ( stud_von <= '2012-01-01' AND '2011-01-01' <= stud_bis )
```

aktuelle Schüler habe NULL bei stud_bis aber das Resultat ist das gleiche

```
WHERE ( stud_von <= '2012-01-01' AND ( stud_bis IS NULL OR '2011-01-01' <= stud_bis ) )
```


----------



## Yitu (19. Sep 2014)

Wie im Startpost geschrieben, kriege ich das nur mit vielen AND's und OR's hin


```
SELECT * FROM `studenten`

WHERE

	(

		(

			stud_von <= '2012-01-01'
			AND
			( stud_bis = 0 OR '2011-01-01' <= stud_bis )

		)

		OR

		(

			( stud_von <= '2011-01-01' AND stud_bis = 0 )

		)

		OR

		(

			( stud_von BETWEEN '2011-01-01' AND '2012-01-01' AND stud_bis = 0 )

		)

	)
```

Die SQL-Ausgabe stimmt aber ich habe ein mulmiges Gefühl. 


Edit:
jetzt gehts :bahnhof:


```
SELECT * FROM `studenten` WHERE ( stud_von <= '2012-01-01' AND ( stud_bis = 0 OR '2011-01-01' <= stud_bis ) )
```

Mit stud_bis IS NULL geht es wohl nicht?

Edit 2

Beim Einpflegen ist ein Startdatum vorhanden, das Enddatum jedoch ist 000-00-00 00:00:00 was eher 0 als NULL entspricht.

Ich werde mal weitere Tests machen, Danke an alle für eure Hilfe. Ich glaube der entscheidende Hinweis kam von Joose?


----------



## Harry Kane (19. Sep 2014)

Im Bereich angemeldet waren alle Studenten, die sich vor dem Startdatum an-, aber erst danach abgemeldet haben, oder die sich nach dem Startdatum aber vor dem Enddatum angemeldet haben, also so etwa:

(stud_von <= '2011-01-01' AND ( stud_bis = 0 OR stud_bis >= '2011-01-01'))// noch angemeldet oder im Zeitraum abgemeldet
or
(stud_von >= '2011-01-01' AND stud_von <= '2012-01-01'))//im Zeitraum angemeldet.

Ui, geht ja noch kürzer.


----------



## Thallius (20. Sep 2014)

Für so eine Abfrage ist es viel einfacher über die Negierung heran zu gehen. In dem Zeitraum angemeldet sind alle, deren Abmeldung NICHT vor dem Startdatum liegt UND deren Anmeldung NICHT nach dem Enddatum liegt.

Das jetzt in eine Query zu bringen überlasse ich dem TO.

Gruss

Claus


----------



## taro (20. Sep 2014)

```
SELECT * FROM studenten WHERE ('2011-01-01' <= stud_bis  OR stud_bis = '0000-00-00') AND '2012-01-01' >= stud_von
```

Die erste "Lösung" war nur etwas verdreht ...

Den Default-Wert für stud_bis halte ich aber persönlich für ungünstig - NULL wäre hier wohl das sinnvollste

EDIT: Huppala ... die Lösung hat der TO ja selbst schon gepostet - es ist halt noch früh und WE ;-)


----------

