문제

이러한 쿼리에서 무의미한 테이블/열 이름에 대해 먼저 사과드립니다.Remedy의 DB 백엔드를 사용해 본 적이 있다면 이해하실 것입니다.

실제 값이 20(23이라고 생각합니다) 어딘가에 있어야 한다고 의심되는 경우 Count Distinct가 null 값을 반환하는 문제가 있습니다.다음은 일련의 쿼리와 해당 반환 값입니다.

SELECT count(distinct t442.c1)
      FROM t442, t658, t631
     WHERE t442.c1 = t658.c536870930
       AND t442.c200000003 = 'Network'
       AND t442.c536871139 < 2
       AND t631.c536870913 = t442.c1
       AND t658.c536870925 = 1
       AND (t442.c7 = 6 OR t442.c7 = 5)
       AND t442.c536870954 > 1141300800
       AND (t442.c240000010 = 0)

결과 = 497.

테이블 t649를 추가하고 테이블 t442에 다시 연결된 레코드가 있는지 확인하세요.

 SELECT COUNT (DISTINCT t442.c1)
              FROM t442, t658, t631, t649
             WHERE t442.c1 = t658.c536870930
               AND t442.c200000003 = 'Network'
               AND t442.c536871139 < 2
               AND t631.c536870913 = t442.c1
               AND t658.c536870925 = 1
               AND (t442.c7 = 6 OR t442.c7 = 5)
               AND t442.c536870954 > 1141300800
               AND (t442.c240000010 = 0)
               AND t442.c1 = t649.c536870914

결과 = 263.

열 c536870939 <= ​​1인 테이블 t649의 레코드를 필터링합니다.

SELECT COUNT (DISTINCT t442.c1)
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1

결과 = 24.

HAVING 문을 필터링합니다.

SELECT COUNT (DISTINCT t442.c1)
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1
        HAVING COUNT (DISTINCT t631.c536870922) =
                                              COUNT (DISTINCT t649.c536870931)

결과 = null입니다.

다음 쿼리를 실행하면 결과 목록에서 어떤 종류의 반환 값도 얻지 못하는 이유를 설명하는 내용을 볼 수 없습니다.SELECT에서 DISTINCT를 제거한 경우에도 마찬가지입니다.(각각 25행과 4265행의 데이터를 돌려받음)

SELECT DISTINCT t442.c1, t631.c536870922, t649.c536870931
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1

null 값을 반환하는 쿼리와 정확히 동일하게 쿼리를 설정하고 완벽하게 작동하는 다른 위치가 여러 군데 있습니다. 즉, 올바른 값인 사용 가능한 숫자를 반환합니다.이 상황에서 고유한 것은 실제 쿼리가 아닌 데이터와 관련되어 있다고 가정해야 하지만 이를 설명하기 위해 데이터에서 무엇을 찾아야 할지 잘 모르겠습니다.집계 전에 원시 데이터에서 null 값을 찾을 수 없었습니다.다른 원인이 무엇인지 모르겠습니다.

어떤 도움이라도 주시면 감사하겠습니다.

도움이 되었습니까?

해결책

지금은 이해.원래 쿼리의 문제는 GROUP BY 절 없이 HAVING 절을 사용하는 것이 매우 이례적이라는 것입니다(실제로 잘못된 것은 아니지만).대답은 쿼리의 다양한 부분이 수행되는 작업 순서에 있습니다.

원래 쿼리에서는 다음을 수행합니다.

SELECT COUNT(DISTINCT t442.c1)
  FROM ...
 WHERE ...
HAVING COUNT(DISTINCT t631.c536870922) = COUNT(DISTINCT t649.c536870931);

데이터베이스는 조인 및 제약 조건을 수행하며, 이 시점에서 그룹화 및 집계 작업을 수행합니다.이 경우 그룹화하지 않으므로 COUNT 작업이 전체 데이터 세트에 걸쳐 수행됩니다.위에 게시한 값을 기준으로 하면 COUNT(DISTINCT t631.c536870922) = 25 및 COUNT(DISTINCT t649.c536870931) = 24입니다.이제 HAVING 절이 적용되어 일치하는 항목이 없습니다. 전체 세트의 개수(여러 개의 c1이 있더라도)가 동일하지만 그렇지 않은 경우를 요청합니다.DISTINCT는 빈 결과 집합에 적용되며 아무 것도 얻지 못합니다.

실제로 수행하려는 작업은 행 수를 뱉어내는 예제에 게시한 내용의 버전일 뿐입니다.

SELECT count(*)
  FROM (SELECT t442.c1     
          FROM t442
             , t658
             , t631
             , t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (   t442.c7 = 6
                OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1
         GROUP BY t442.c1
        HAVING COUNT(DISTINCT t631.c536870922) = COUNT(DISTINCT t649.c536870931)
       );

그러면 631 및 649 테이블 항목의 수가 동일한 c1 열 목록이 제공됩니다.메모:쿼리에서 DISTINCT를 사용할 때는 매우 주의해야 합니다.예를 들어, 위의 결과를 게시한 경우에는 전혀 필요하지 않습니다.WHERE 절에서 누락된 제약 조건으로 인해 원하는 방식으로 결과를 반환하지 않는 쿼리의 오류를 덮기 위한 일종의 배경 화면 역할을 하는 경우가 많습니다("흠, 내 쿼리는 이 모든 값에 대해 속이는 값을 반환하고 있습니다.음, DISTINCT가 그 문제를 해결할 것입니다.")

다른 팁

결과는 무엇입니까?

SELECT COUNT (DISTINCT t631.c536870922),
       COUNT (DISTINCT t649.c536870931)
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1

두 열의 값이 동일하지 않은 경우 HAVING 절을 추가하면 결과 집합에서 모든 행이 제거되는 것이 합리적입니다.

COUNT(DISTINCT column) 계산하지 않는다 NULL 값:

SELECT  COUNT(DISTINCT val1)
FROM    (
        SELECT  NULL AS val1
        FROM    dual
        )

---
0

그럴 수도 있나요?

대신 WHERE 절에 HAVING 절 조건을 넣어 보겠습니다.HAVING을 선택한 이유가 있나요?참고로 HAVING은 결과 집합이 반환된 후에 수행되는 필터이므로 예기치 않은 결과가 발생할 수 있습니다.또한 쿼리 최적화에는 사용되지 않습니다.HAVING을 사용할 필요가 없다면 사용하지 않는 것이 좋습니다.

SELECT 절에 개수를 추가한 다음 WHERE 절에 결합하는 것이 좋습니다.

내가 이렇게 하면:

SELECT distinct t442.c1, count(distinct t631.c536870922), 
    count (distinct t649.c536870931)
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1
           group by t442.c1
           having count(distinct t631.c536870922)= 
                         count (distinct t649.c536870931)

계산해야 할 23개의 행이 보입니다.HAVING 문을 제거하면 24개의 행이 반환되는데, 추가 행은 해당 HAVING 기준을 충족하지 않습니다.

편집하다:Steve Broberg가 요청한 쿼리 결과:

row | t442.c1         | cnt t631 | cnt 649
-------------------------------------------
1   | CHG000000230378 |    2     |    1
2   | CHG000000230846 |    1     |    1
3   | CHG000000232562 |    1     |    1
4   | CHG000000232955 |    1     |    1
5   | CHG000000232956 |    1     |    1
6   | CHG000000232958 |    1     |    1
7   | CHG000000233027 |    1     |    1
8   | CHG000000233933 |    1     |    1
9   | CHG000000233934 |    1     |    1
10  | CHG000000233997 |    1     |    1
11  | CHG000000233998 |    1     |    1
12  | CHG000000233999 |    1     |    1
13  | CHG000000234001 |    1     |    1
14  | CHG000000234005 |    1     |    1
15  | CHG000000234009 |    1     |    1
16  | CHG000000234012 |    1     |    1
17  | CHG000000234693 |    1     |    1
18  | CHG000000234696 |    1     |    1
19  | CHG000000234730 |    1     |    1
20  | CHG000000234839 |    1     |    1
21  | CHG000000235115 |    1     |    1
22  | CHG000000235224 |    1     |    1
23  | CHG000000235488 |    1     |    1
24  | CHG000000235847 |    1     |    1 

HAVING 절을 포함하면 첫 번째 행이 제대로 필터링됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top