문제

단순화 된 테이블 구조 :

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

이 쿼리는 단순화되어 관련된 데이터와 질문에 영향을 미치지 않아야 할 추가 열을 제거했습니다.

Max (Active_date)는 특정 날의 모든 레코드에 대해 동일하며 항상 가장 최근의 날을 선택하거나 지금부터 ()을 허용해야합니다. (Unixtime 필드입니다)

(상태! = 'OK'및 상태! = '수리')의 수를 모두 원합니다.

그리고 역수 ... (status = 'ok'또는 status = '수리')

그리고 첫 번째 답변은 '백분율 _dead'에 대해 두 번째 답변으로 나뉘어져 있습니다 (아마도 포스트 처리에서 빠르게 할 것입니다).

가장 최근의 날 또는 오프셋 (-86400의 경우 86400 등).

테이블은 약 500K 레코드가 포함되어 있으며 하루에 약 5000 씩 증가하므로 루핑과 달리 단일 SQL 쿼리가 정말 좋을 것입니다 ..

나는 이것을 할 수 있다면 창의적이라고 생각합니다. 당신의 전문 지식에 감사드립니다.

편집 : 오늘날의 데이터 또는 오프셋의 데이터에 대해 다른 SQL 쿼리를 사용할 수 있습니다.

편집 : 쿼리 작동은 빠르지 만 충분히 빠르지 만 현재 사용자가 백분율 열 (나쁜 수와 좋은 수에서 파생 된 것)을 정렬 할 수는 없습니다. 이것은 쇼 스토퍼가 아니지만 다른 모든 것을 분류 할 수 있습니다. 이것의 순서 :

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의 상태를 얻지 않으려 고합니다. 오른쪽? 그런 다음 Core로 그룹화해야합니다.

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;

이것은 StackoverFlow에서 SQL 질문에서 많은 것을 볼 수있는 "그룹당 가장 큰 그룹"문제의 변형입니다.

먼저 호스트 이름 당 최신 활동 날짜가있는 행 만 선택하려고합니다. 이는 동일한 호스트 이름과 더 큰 활성 _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; 

OK와 깨진 호스트 이름의 비율과 관련하여 PHP 코드에서이를 계산하는 것이 좋습니다. 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