2013-07-26 7 views
0

데이터베이스에 대한 테스트가 있는데 이상한 이유로 임의로 다른 결과 집합을 반환합니다. 흥미롭게도 수천 개의 행에서 반환하는 유일한 결과 집합은 두 가지 뿐이며 쿼리는 무작위로 하나를 반환하지만 다른 것은 반환하지 않습니다.MySQL의 이상한 쿼리 결과

쿼리가 두 데이터 집합 중 하나만 반환하는 이유가 있습니까? 아래 쿼리 및 스키마.

나의 목표는 주어진 시간 동안 주어진 트랙에 대해 가장 빠른 랩을 선택하는 것이지만, 각 사용자에 대해 가장 빠른 랩 만 사용하는 것입니다. 따라서 톱 10에는 항상 10 명의 다른 사용자가 있습니다.

대부분의 경우 올바른 결과가 반환되지만 무작위 적으로 완전히 다른 결과 집합이 반환됩니다.

SELECT `lap`.`ID`, `lap`.`qualificationTime`, `lap`.`userId` 
FROM `lap` 
WHERE (lap.trackID =4) 
AND (lap.raceDateTime >= "2013-07-25 10:00:00") 
AND (lap.raceDateTime < "2013-08-04 23:59:59") 
AND (isTestLap =0) 
GROUP BY `userId` 
ORDER BY `qualificationTime` ASC 
LIMIT 10 

스키마 :

CREATE TABLE IF NOT EXISTS `lap` (
    `ID` int(11) NOT NULL AUTO_INCREMENT, 
    `userId` int(11) DEFAULT NULL, 
    `trackId` int(11) DEFAULT NULL, 
    `raceDateTime` datetime NOT NULL, 
    `qualificationTime` decimal(7,4) DEFAULT '0.0000', 
    `isTestLap` int(11) NOT NULL DEFAULT '0', 
PRIMARY KEY (`ID`) 

당신은 lap.ID, lap.qualificationTimelap.userId을 선택하는

+0

ID가 가장 빠른 랩이 필요한가 아니면 잠깐입니까? – Uriil

+0

@Uriil 실제로 ID 만 필요합니다. qualificationTime 및 userId 행이이 문제를 디버깅하기 위해 선택되고 있습니다. – dKen

+0

동일한 사용자의 두 바퀴가 동일한 지속 시간을 갖는 경우 어떻게해야합니까? – Uriil

답변

1

. 다른 사람들이 지적한대로 group by에없는 열을 select 문에 넣을 수 있습니다. 그러나 반환 값은 임의적이며 실행 간 동일성이 보장되지 않습니다.

해결책은 각 사용자의 최대 인증 시간을 찾는 것입니다. 그런 다음이 정보를 다시 결합하여 다른 필드를 가져옵니다. 한 가지 방법이 있습니다.

select l.* 
from (SELECT userId, min(qualificationtime) as minqf 
     FROM lap 
     WHERE (lap.trackID =4) 
     AND (lap.raceDateTime >= "2013-07-25 10:00:00") 
     AND (lap.raceDateTime < "2013-08-04 23:59:59") 
     AND (isTestLap =0) 
     GROUP BY `userId` 
    ) lu join 
    lap l 
    on lu.minqf = l.qualificationtime 
ORDER BY l.`qualificationTime` ASC 
LIMIT 10 
+0

고든에게 감사드립니다. 하위 쿼리가 테이블의 모든 랩에 대해 실행된다는 것을 의미합니까? 나는 원래의 쿼리에서 비슷한 것을 가졌지 만 올바르게 확장되지 않아 두 쿼리로 분리하는 경로를 택한 것입니다. 위 쿼리에 0.2 초가 소요됩니다. 랩 테이블과 사용자 수가 늘어남에 따라 확장 성이 있다고 생각합니까? – dKen

+0

@ dKen. . . 나는 쿼리가 괜찮을 것이라고 생각한다. 그러나 스케일링은 흥미 롭습니다 (항상 그렇습니다). 'TrackId, IsTestLap, raceDateTime'에 복합 인덱스가 있다면 성능은 좋아질 것입니다. 그렇지 않으면 집계를 수행하기 전에 전체 랩 테이블을 스캔해야합니다. 성과가 문제가되면 다른 질문을하십시오. –

1

(DB 해제 필요한 컬럼의 손질 스크립트를 작성), 그러나 당신이 그 (것)들을하지 GROUPing BY 있습니다. 필드를 선택하거나 다른 필드 (MIN, MAX, AVG 등)의 기능을 집계 할 수 있습니다. 그렇지 않으면 결과가 정의되지 않습니다.

+0

Thanks Nitzan. 이 문제를 해결하기 위해 내가해야 할 일이 있습니까? 일반적으로 나는 아이디어를 가지고 있지만,이 경우에는 길을 잃는다. – dKen

+0

물론. 결과 세트에서 원하는 것은 무엇입니까? 각각의 userId가있는 행 세트는 ... 또 뭐야? –

+0

고마워. 사실 랩의 ID가 필요합니다 (qualificationTime 및 userId가 디버깅을 위해 바로 존재했습니다).그 ID를 나중에 가져 와서 더 많은 정보를 얻을 필요가 있습니다. – dKen

0

가끔 lap에 대한 값이 있다고 생각합니다. ID, lap. qualificationTime은 다릅니다. 그리고 그것은 mysql에 올바른 행동입니다. 그룹을 userId으로 그룹화했기 때문에 다른 필드의 값이 반환 될지 알 수 없습니다. MySQL은 첫 번째 값 또는 마지막 행 읽기에 따라 다른 값을 선택할 수 있습니다.

+0

감사합니다 Andrej, 올바른 결과를 반환하려면 내 쿼리를 변경하는 방법을 생각해 보셨나요? – dKen

0

10 진수 엔티티의 ORDER BY가 될 가능성이 높으며 DB가이를 저장하고 검색하는 방법입니다. 당신이 얻을 수있는 두 가지 결과를 공유 할 수 있습니까?

0

나는 이런 식으로 뭔가를 확인합니다 : MySQL은 숨겨진 열을 전화의 당신은 (MIS) 기능을 사용하는

SELECT `l1`.`qualificationTime`, `l1`.`userId`, 
      (SELECT l2.ID FROM `lap` AS l2 WHERE l2.`userId` = l1.userId AND 
      l2.qualificationTime = min(l1.`qualificationTime`)) 
    FROM `lap` AS `l1` 
    WHERE (l1.trackID =4) 
      AND (l1.raceDateTime >= "2013-07-25 10:00:00") 
      AND (l1.raceDateTime < "2013-08-04 23:59:59") 
      AND (isTestLap =0) 
    GROUP BY `userId` 
    ORDER BY `qualificationTime` ASC 
    LIMIT 10 
+0

감사합니다. 이것은 실제로 내가 시작한 것입니다. 그리고 이제 1,000 개의 행과 사용자가 생겨났습니다. 서브 쿼리가 나를 죽이고 있습니다. 모든 사용자 (수천 일 수 있음)에 대해 하위 쿼리를 실행 한 다음 나중에 상위 10 개만 선택합니다. 그것은 너무 비효율적입니다. 그래서 저는 위의 다른 경로를 시도하고 있습니다. – dKen