سؤال

والمبسطة هيكل الجدول:

CREATE TABLE IF NOT EXISTS `hpa` (
  `id` bigint(15) NOT NULL auto_increment,
  `core` varchar(50) NOT NULL,
  `hostname` varchar(50) NOT NULL,
  `status` varchar(255) NOT NULL,
  `entered_date` int(11) NOT NULL,
  `active_date` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `hostname` (`hostname`),
  KEY `status` (`status`),
  KEY `entered_date` (`entered_date`),
  KEY `core` (`core`),
  KEY `active_date` (`active_date`)
)

لذلك، لدي الاستعلام SQL التالية التي تبلغ ببساطة كل الأرقام القياسية مع وضع محددة.

SELECT core,COUNT(hostname) AS hostname_count, MAX(active_date) AS last_active
          FROM `hpa`
          WHERE 
          status != 'OK' AND status != 'Repaired'
          GROUP BY core
          ORDER BY core

لقد تم تبسيط هذا الاستعلام لإزالة INNER تنضم إلى البيانات لا علاقة لها والأعمدة الإضافية التي يجب أن لا يؤثر هذا السؤال.

وMAX (active_date) هو نفسه بالنسبة لجميع السجلات من يوم معين، ويجب تحديد دائما في اليوم الأخير، أو السماح إزاحة من NOW (). (هو حقل UNIXTIME)

وأريد كل من عدد من: (!! الحالة = 'موافق' ووضع = 'إصلاحها')

ومعكوس ... عد من: (الحالة = 'موافق' OR الحالة = 'إصلاحها')

والإجابة الأولى مقسوما على الثانية، ل 'percentage_dead "(ربما فقط بسرعة كما تفعل في مرحلة ما بعد المعالجة)

FOR اليوم الأخير أو إزاحة (- 86400 يوم أمس، الخ ..)

والجدول يحتوي على حوالي 500K السجلات وينمو بنحو 5000 يوم حتى استعلام SQL واحد بدلا من حلقات ستكون حقيقية لطيفة ..

وأتصور بعض خلاقة IF يمكن أن تفعل هذا. هل هو موضع تقدير الخبرة.

وتحرير: أنا مستعد لاستخدام استعلام SQL مختلفة إما البيانات اليوم، أو بيانات من إزاحة

.

وتحرير: يعمل الاستعلام سريع بما فيه الكفاية، ولكن أنا حاليا لا يمكن السماح للمستخدمين فرز على العمود نسبة (واحد مستمد من التهم سيئة وجيدة). هذا ليس عرض سدادة، ولكن أسمح لهم لفرز على كل شيء آخر. وORDER BY هذا:

SELECT h1.core, MAX(h1.entered_date) AS last_active, 
SUM(CASE WHEN h1.status IN ('OK', 'Repaired') THEN 1 ELSE 0 END) AS good_host_count,  
SUM(CASE WHEN h1.status IN ('OK', 'Repaired') THEN 0 ELSE 1 END) AS bad_host_count 
FROM `hpa` h1 
LEFT OUTER JOIN `hpa` h2 ON (h1.hostname = h2.hostname AND h1.active_date < h2.active_date) 
WHERE h2.hostname IS NULL 
GROUP BY h1.core 
ORDER BY ( bad_host_count / ( bad_host_count + good_host_count ) ) DESC,h1.core

ويعطي لي:     # 1247 - المرجع "bad_host_count" غير معتمد (إشارة إلى وظيفة مجموعة)

وتحرير: حل لمقطع آخر. الأعمال التالية، ويسمح لي أن ORDER BY percentage_dead

SELECT c.core, c.last_active, 
SUM(CASE WHEN d.dead = 1 THEN 0 ELSE 1 END) AS good_host_count,  
SUM(CASE WHEN d.dead = 1 THEN 1 ELSE 0 END) AS bad_host_count,
( SUM(CASE WHEN d.dead = 1 THEN 1 ELSE 0 END) * 100/
( (SUM(CASE WHEN d.dead = 1 THEN 0 ELSE 1 END) )+(SUM(CASE WHEN d.dead = 1 THEN 1 ELSE 0 END) ) ) ) AS percentage_dead
FROM `agent_cores` c 
LEFT JOIN `dead_agents` d ON c.core = d.core
WHERE d.active = 1
GROUP BY c.core
ORDER BY percentage_dead
هل كانت مفيدة؟

المحلول

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

SELECT core, MAX(active_date)
  SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 1 ELSE 0 END) AS OK_host_count,
  SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 0 ELSE 1 END) AS broken_host_count
FROM `hpa` h1 LEFT OUTER JOIN `hpa` h2 
  ON (h1.hostname = h2.hostname AND h1.active_date < h2.active_date)
WHERE h2.hostname IS NULL
GROUP BY core
ORDER BY core;

وهذا هو الاختلاف من المشكلة "أعظم ن لكل جماعة" الذي أراه كثيرا في الأسئلة SQL على ستاكوفيرفلوو.

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

وبعد ذلك مجموعة من صميم والاعتماد الصفوف حسب الحالة.

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

SELECT core, MAX(active_date)
  SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 1 ELSE 0 END) AS OK_host_count,
  SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 0 ELSE 1 END) AS broken_host_count
FROM `hpa` h1 LEFT OUTER JOIN `hpa` h2 
  ON (h1.hostname = h2.hostname AND h1.active_date < h2.active_date
  AND h2.active_date <= CURDATE() - INTERVAL 1 DAY)
WHERE h1.active_date <= CURDATE() - INTERVAL 1 DAY AND h2.hostname IS NULL
GROUP BY core
ORDER BY core; 

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


ولقد نسيت قلت لك كنت تستخدم الطابع الزمني UNIX. تفعل شيئا مثل هذا:

SELECT core, MAX(active_date)
  SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 1 ELSE 0 END) AS OK_host_count,
  SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 0 ELSE 1 END) AS broken_host_count
FROM `hpa` h1 LEFT OUTER JOIN `hpa` h2 
  ON (h1.hostname = h2.hostname AND h1.active_date < h2.active_date
  AND h2.active_date <= UNIX_TIMESTAMP() - 86400)
WHERE h1.active_date <= UNIX_TIMESTAMP() - 86400 AND h2.hostname IS NULL
GROUP BY core
ORDER BY core; 
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top