Frage

Hey, stieß ich auf dieser Seite der Suche nach Lösungen für die Veranstaltung in mySQL-Tabellen überlappt. Ich war so beeindruckt von der Lösung (die hilft schon) Ich dachte, ich würde sehen, ob ich etwas mehr Hilfe bekommen könnte ...

Okay, so Joe will die Verschiebungen bei der Arbeit mit jemandem tauschen. Er hat einen Gerichtstermin. Er geht auf die Verschiebung Swap Form und es in dieser Woche Zeitplan nach oben ziehen (oder was davon übrig ist). Dies wird mit einer DB-Abfrage durchgeführt. Kein Schweiß. Er nimmt eine Verschiebung. Ab diesem Zeitpunkt wird es stachelig.

Also, zuerst, so geht die Form der Schichtbeginn und -ende an das Skript. Es führt eine Abfrage für alle, die eine Verschiebung hat, die diese Verschiebung überlappt. Sie können nicht zwei Schichten arbeiten auf einmal, so dass alle Benutzer-IDs aus dieser Abfrage werden auf eine schwarze Liste setzen. Diese Abfrage wie folgt aussieht:

SELECT DISTINCT user_id FROM shifts
WHERE
FROM_UNIXTIME('$swap_shift_start') < shiftend
AND FROM_UNIXTIME('$swap_shift_end') > shiftstart

Als nächstes führen wir eine Abfrage für alle Schichten, die a) die gleiche Länge (Unternehmenspolitik) sind, und b) überlappen sich nicht mit anderen Verschiebungen Joe arbeitet.

Was ich zur Zeit haben, ist so etwas wie folgt aus:

SELECT *
FROM shifts
AND shiftstart BETWEEN  FROM_UNIXTIME('$startday') AND FROM_UNIXTIME('$endday')
AND user_id NOT IN ($busy_users) 
AND (TIME_TO_SEC(TIMEDIFF(shiftend,shiftstart)) = '$swap_shift_length')
$conflict_dates
ORDER BY shiftstart, lastname

Jetzt sind Sie wahrscheinlich fragen, "was $ conflict_dates ist ???"

Nun, wenn Joe die Swap-Verschiebung vorträgt, lädt es seine Verschiebungen für die Woche, falls er eine weitere Verschiebung Potenzial zu überprüfen, entscheidet. Also, wenn es tut, dass erste Abfrage, während das Skript durch geloopt und seine Entscheidungen ausgibt, wird es auch einen String bauen, die Art wie folgt aussieht:

AND NOT(
'joe_shift1_start' < shiftend
AND 'joe_shift1_end' > shiftstart)
AND NOT(
'joe_shift2_start' < shiftend
AND 'joe_shift2_end' > shiftstart)
...etc

Damit die Datenbank der eine ziemlich lange Abfrage entlang der Linien von:

SELECT *
FROM shifts
AND shiftstart BETWEEN  FROM_UNIXTIME('$startday') AND FROM_UNIXTIME('$endday')
AND user_id NOT IN ('blacklisteduser1', 'blacklisteduser2',...etc) 
AND (TIME_TO_SEC(TIMEDIFF(shiftend,shiftstart)) = '$swap_shift_length')
AND NOT(
'joe_shift1_start' < shiftend
AND 'joe_shift1_end' > shiftstart)
AND NOT(
'joe_shift2_start' < shiftend
AND 'joe_shift2_end' > shiftstart)
AND NOT(
'joe_shift3_start' < shiftend
AND 'joe_shift3_end' > shiftstart)
AND NOT(
'joe_shift4_start' < shiftend
AND 'joe_shift4_end' > shiftstart)
...etc
ORDER BY shiftstart, lastname

Also, meine Hoffnung ist, dass entweder SQL einige Genie Art und Weise hat mit diesem in einer einfacheren Art und Weise des Umgangs, oder dass jemand kann ein fantastisches logisches Haupt weist darauf hin, dass für die möglichen Konflikte in eine viel intelligentere Weise ausmacht. (Beachten Sie die Verwendung des ‚Start> Ende, Ende

Danke!

A

War es hilfreich?

Lösung

Ich glaube, Sie sollten Joes andere Verschiebungen der Lage sein, ausschließen eine innere wählen Sie anstelle der erzeugten Zeichenfolge verwendet wird, so etwas wie:

SELECT *
FROM shifts s1
AND shiftstart BETWEEN  FROM_UNIXTIME('$startday') AND FROM_UNIXTIME('$endday')
AND user_id NOT IN ($busy_users) 
AND (TIME_TO_SEC(TIMEDIFF(shiftend,shiftstart)) = '$swap_shift_length')
AND (SELECT COUNT(1) FROM shifts s2
     WHERE s2.user_id = $joes_user_id
     AND   s1.shiftstart < s2.shiftend
     AND   s2.shiftstart < s1.shiftend) = 0
ORDER BY shiftstart, lastname

Grundsätzlich hat jede Zeile eine innere Abfrage für die Zählung von Joes Verschiebungen, die sich überlappen, und stellt sicher, dass es Null. Somit werden nur die Zeilen, die mit einem der Joe bestehenden Verschiebungen zurückgegeben werden nicht überlappen.

Andere Tipps

Sie könnten die joe_shift{1,2,3} Werte in eine temporäre Tabelle laden und dann eine Abfrage gegen sie zu verbinden, eine Außen mit join nur Verschiebung zu finden, die nicht passen:

CREATE TEMPORARY TABLE joes_shifts (
 shiftstart DATETIME
 shiftend   DATETIME
);
INSERT INTO joes_shifts (shiftstart, shiftend) VALUES
  ('$joe_shift1_start', '$joe_shift1_end'),
  ('$joe_shift2_start', '$joe_shift2_end'),
  ('$joe_shift3_start', '$joe_shift3_end'),
  ('$joe_shift4_start', '$joe_shift4_end');
-- make sure you have validated these variables to prevent SQL injection

SELECT s.*
FROM shifts s
  LEFT OUTER JOIN joes_shifts j
  ON (j.shiftstart < s.shiftend OR j.shiftend > s.shiftstart) 
WHERE j.shiftstart IS NULL
  AND s.shiftstart BETWEEN FROM_UNIXTIME('$startday') AND FROM_UNIXTIME('$endday')
  AND s.user_id NOT IN ('blacklisteduser1', 'blacklisteduser2',...etc) 
  AND (TIME_TO_SEC(TIMEDIFF(s.shiftend,s.shiftstart)) = '$swap_shift_length');

Aufgrund der LEFT OUTER JOIN, wenn es keine passende Zeile in joes_shifts ist, die Spalten sind NULL.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top