سؤال

مهلا، تعثرت على هذا الموقع بحثا عن حلول للتداخل في جداول MySQL. كنت أعجبت جدا بالحل (الذي يساعد بالفعل) اعتقدت أنني أرى ما إذا كان بإمكاني الحصول على المزيد من المساعدة ...

حسنا، لذلك نريد جو التحولات مع شخص ما في العمل. لديه تاريخ المحكمة. يذهب إلى نموذج مبادلة التحول وسحب جدول هذا الأسبوع (أو ما تبقى منه). يتم ذلك باستخدام استعلام DB. لا عرق. انه يختار التحول. من هذه النقطة، يحصل الشائك.

لذلك، أولا، يمرر النموذج بدء تشغيل التحول ونقل نهاية البرنامج النصي. إنه يدير استعلام لأي شخص لديه تحول يتداخل هذا التحول. لا يمكنهم العمل اثنين من التحولات في وقت واحد، لذلك يتم وضع جميع معرفات المستخدم من هذا الاستعلام على قائمة سوداء. يبدو هذا الاستعلام:

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

بعد ذلك، ندير استعلام لجميع التحولات التي هي نفس الطول (سياسة الشركة)، و B) لا تتداخل مع أي نوبات أخرى جو يعمل.

ما لدي حاليا شيء مثل هذا:

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

الآن، ربما تتساءل "ما هو النزاعات $_ ؟؟؟"

حسنا، عندما يقدم جو نوبة مبادلة، فإنه يعيد تحميل نوباته للأسبوع في حالة قرر التحقق من إمكانات التحول الأخرى. لذلك عندما يقوم بذلك الاستعلام الأول، في حين أن البرنامج النصي يحل محل اختياراته وإخراجها، فإنه يبني أيضا سلسلة تبدو مثل:

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

بحيث تكون قاعدة البيانات تحصل على استعلام طويل جميل على غرار:

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

لذلك، آمل أن يكون إما SQL طريقة عبقرية للتعامل مع هذا بطريقة أبسط، أو أن شخصا ما يمكن أن يشير إلى مدير منطقي رائع يمثل النزاعات المحتملة بطريقة أكثر ذكاء بكثير. (لاحظ استخدام "نهاية البداية>، النهاية <start"، قبل أن أجد أنني كنت أستخدم Betweens واضطررت إلى طرح دقيقة واحدة من طرفي.)

شكرا!

أ

هل كانت مفيدة؟

المحلول

أعتقد أنه يجب أن تكون قادرا على استبعاد التحولات الجوية الأخرى باستخدام اختيار داخلي بدلا من السلسلة التي تم إنشاؤها، شيء مثل:

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

في الأساس، يحتوي كل صف على استعلام داخلي لعدد نوبات جو تتداخل، وتأكد من أنه صفر. وبالتالي، سيتم إرجاع الصفوف فقط التي لا تتداخل مع أي من التحولات الجوية الحالية.

نصائح أخرى

يمكنك تحميل joe_shift{1,2,3}القيم في جدول مؤقت ثم قم بإجراء استعلام للانضمام إليه، باستخدام انضمام خارجي للعثور فقط على التحول الذي لا يتطابق مع أي:

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');

بسبب الانضمام الخارجي الأيسر، عندما لا يكون هناك صف مطابق في joes_shifts, ، الأعمدة فارغة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top