복붙노트

[SQL] COUNT (*) 대 수 (1) 대 수 (PK) : 더 나은 무엇입니까? [복제]

SQL

COUNT (*) 대 수 (1) 대 수 (PK) : 더 나은 무엇입니까? [복제]

나는 종종이 세 가지 변종을 찾을 수 있습니다 :

SELECT COUNT(*) FROM Foo;
SELECT COUNT(1) FROM Foo;
SELECT COUNT(PrimaryKey) FROM Foo;

최대한 멀리 볼 수, 그들은 모두 같은 일을하고, 내 코드베이스의 3을 사용하여 자신을 찾을 수 있습니다. 그러나, 나는 같은 일을 여러 가지 방법을 좋아하지 않아요. 어느 하나에 나는 충실해야한다고? 어떤 두 개의 다른 사람보다 그들 중 하나가 더 나은가요?

해결법

  1. ==============================

    1.일관되게과 중 COUNT (필드) 또는 COUNT (*), 스틱을 사용하여 데이터베이스가 허용하는 경우 COUNT (tableHere) 또는 COUNT (tableHere. *) 사용하는 것이.

    일관되게과 중 COUNT (필드) 또는 COUNT (*), 스틱을 사용하여 데이터베이스가 허용하는 경우 COUNT (tableHere) 또는 COUNT (tableHere. *) 사용하는 것이.

    즉, 아무것도 COUNT (1)를 사용하지 않습니다. 그것은 거의 당신이 원하는 것을하지 않습니다 원 트릭 포니,, 그리고 그 드문 경우에 수에 해당합니다 (*)

    필요, 결합도에 대한 사용을 모든 카운트하는 모든 쿼리에 대한 사용 * *

    SELECT boss.boss_id, COUNT(subordinate.*)
    FROM boss
    LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
    GROUP BY boss.id
    

    하위 테이블이 부모 테이블에서 아무것도 일치하지 않는 경우에도 그 일을 반환하지만, LEFT 조인에 대한 COUNT (*)를 사용하지 않는

    SELECT boss.boss_id, COUNT(*)
    FROM boss
    LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
    GROUP BY boss.id
    

    COUNT에 *를 사용하는 경우, 그것은 그 *이 느린 말, 테이블에서 전체 행을 반입하는 조언들에 속지 마십시오. SELECT 수 (*)를 선택 함 * * *은 그들이 그들이 단지 일반적인 토큰을 공유하도록, 즉 완전히 다른 건, 서로 전혀 관계가 없다.

    그것의 테이블 이름과 동일 필드 이름을 허용하지 않을 경우 사실, RDBMS 언어 디자이너는 COUNT (tableNameHere) COUNT (*)와 같은 의미를 줄 수 있습니다. 예:

    계산 행의 경우 우리는 이것을 할 수 :

    SELECT COUNT(emp) FROM emp
    

    그리고 그들은 그것을 간단하게 만들 수 :

    SELECT COUNT() FROM emp
    

    LEFT 조인을 위해, 우리는 이것을 할 수 :

    SELECT boss.boss_id, COUNT(subordinate)
    FROM boss
    LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
    GROUP BY boss.id
    

    그러나 그들은 그것의 테이블 이름과 같은 이름의 필드 이름을 지정 SQL 표준 허용 이후 그 (COUNT (tableNameHere))를 수행 할 수 없습니다

    CREATE TABLE fruit -- ORM-friendly name
    (
    fruit_id int NOT NULL,
    fruit varchar(50), /* same name as table name, 
                    and let's say, someone forgot to put NOT NULL */
    shape varchar(50) NOT NULL,
    color varchar(50) NOT NULL
    )
    

    또한, 그것의 이름은 테이블 이름과 일치하는 경우 필드 널 (NULL)을 만들 수있는 좋은 방법이 아닙니다. 당신이 값 '바나나'을 말해봐 '애플', NULL, 과일 필드에서 '배'. 이것은 모든 행을 계산하지 않습니다 만 4, 3을 얻을하지 않습니다

    SELECT count(fruit) FROM fruit
    

    일부 RDBMS 원칙의 종류를 할 수 있지만 어떤 하위 필드 길이가 한 예를 아래에 두 테이블 중 어느이없는 경우이 (PostgreSQL을에서 작동합니다 (테이블의 행을 카운트를 들어, COUNT의 매개 변수로 테이블 이름을 허용) 아니오) 필드 이름과 테이블 이름 사이의 충돌 이름 :

    SELECT boss.boss_id, COUNT(subordinate)
    FROM boss
    LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
    GROUP BY boss.id
    

    이 (널 (NULL)이 될 수 있음) 분야를 계산합니다 우리가, 표에없는 테이블 행을 하위 필드를 추가합니다하지만 그 이후 혼란의 원인이 될 수 있습니다.

    그래서 안전을 위해, 사용 :

    SELECT boss.boss_id, COUNT(subordinate.*)
    FROM boss
    LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
    GROUP BY boss.id
    

    특히 (1) COUNT하기 위해, 그것은 하나 개의 테이블 쿼리에서 잘 작동 한 트릭 포니입니다 :

    SELECT COUNT(1) FROM tbl
    

    그러나 사용할 때 그 트릭은 의미가없는 멀티 테이블 쿼리에없는 작업이 혼동되는 것, 특히 당신이 쓸 수 없습니다, 조인

    -- count the subordinates that belongs to boss
    SELECT boss.boss_id, COUNT(subordinate.1)
    FROM boss
    LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
    GROUP BY boss.id
    

    그래서 여기 COUNT (1)의 의미는 무엇인가?

    SELECT boss.boss_id, COUNT(1)
    FROM boss
    LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
    GROUP BY boss.id
    

    그것은이다 ...?

    -- counting all the subordinates only
    SELECT boss.boss_id, COUNT(subordinate.boss_id)
    FROM boss
    LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
    GROUP BY boss.id
    

    아니면 이거...?

    -- or is that COUNT(1) will also count 1 for boss regardless if boss has a subordinate
    SELECT boss.boss_id, COUNT(*)
    FROM boss
    LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
    GROUP BY boss.id
    

    신중하게 생각하면 그 COUNT (1)에 관계없이 가입의 종류, COUNT (*)와 동일한 추론 할 수있다. LEFT이 결과를 조인을 위해, 우리는 같은 일에 COUNT (1)를 성형 할 수 없습니다. (하위 *) COUNT (subordinate.boss_id), COUNT

    그래서 바로 다음 중 하나를 사용합니다 :

    -- count the subordinates that belongs to boss
    SELECT boss.boss_id, COUNT(subordinate.boss_id)
    FROM boss
    LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
    GROUP BY boss.id
    

    PostgreSQL을에 작품, 당신이 세트의 중요도를 계산 할 것이 분명

    -- count the subordinates that belongs to boss
    SELECT boss.boss_id, COUNT(subordinate.*)
    FROM boss
    LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
    GROUP BY boss.id
    

    또 다른 방법은 매우 영어-(같은 단지의 테이블 이름과 동일한 이름을 가진 열을하지 않는다) 세트의 중요도를 계산하는 방법 : http://www.sqlfiddle.com/#!1/98515/7

    select boss.boss_name, count(subordinate)
    from boss
    left join subordinate on subordinate.boss_code = boss.boss_code
    group by boss.boss_name
    

    당신은이 작업을 수행 할 수 없습니다 http://www.sqlfiddle.com/#!1/98515/8

    select boss.boss_name, count(subordinate.1)
    from boss
    left join subordinate on subordinate.boss_code = boss.boss_code
    group by boss.boss_name
    

    당신은이 작업을 수행 할 수 있지만,이 잘못된 결과를 생성 : http://www.sqlfiddle.com/#!1/98515/9

    select boss.boss_name, count(1)
    from boss
    left join subordinate on subordinate.boss_code = boss.boss_code
    group by boss.boss_name
    
  2. ==============================

    2.그 중 두 항상 같은 대답을 생산 :

    그 중 두 항상 같은 대답을 생산 :

    약동학 가정하면에는 널이어서, 값으로 허용되는 기본 키이며

    PK가 NOT NULL로 제한되어 있지 않은 경우, 그것은 다른 대답을 생성합니다

    일반적으로, 나는 COUNT (*)를 쓰기; 그것은 SQL의 원래 권장 표기법입니다. 절로 존재와 존재하는 그 때문에 원래 표기법을 추천했다 마찬가지로, 나는 일반적으로 (... SELECT * FROM) 물품. 대안 아무런 혜택이 없을 것; 옵티마이 저는 더 애매한 표기법을 통해 볼 수 있습니다.

  3. ==============================

    3.이것은 당신이 사용하고있는 데이터베이스의 종류뿐만 아니라 경우에 따라 테이블의 유형에 따라 달라집니다.

    이것은 당신이 사용하고있는 데이터베이스의 종류뿐만 아니라 경우에 따라 테이블의 유형에 따라 달라집니다.

    MySQL을 사용 예를 들어, (*)는 이노 아래 MyISAM 테이블하지만 느린에서 빠른 것입니다 계산합니다. 이노에서 당신은 수 (1)을 사용하거나 (PK) 계산한다.

  4. ==============================

    4.질문과 전에 대답 ...

    질문과 전에 대답 ...

    온라인 도서는 "COUNT ({* [| | DISTINCT] 식 [전체]})"라고

    이 COUNT (*)와 동일한 그래서 "1"비 - 널 식이다. 옵티마이 사소한로 인식 때문에 같은 계획을 제공합니다. PK가 고유 및 비 - 널 (SQL 서버 적어도) COUNT 그렇다 (PK) = COUNT (*)

    이것은 ... EXISTS (SELECT * 유사한 신화 또는 (1을 선택 EXISTS ...

    그리고 ANSI 92 사양, 섹션 6.5, 일반 규칙, 사례 1 참조

            a) If COUNT(*) is specified, then the result is the cardinality
              of T.
    
            b) Otherwise, let TX be the single-column table that is the
              result of applying the <value expression> to each row of T
              and eliminating null values. If one or more null values are
              eliminated, then a completion condition is raised: warning-
              null value eliminated in set function.
    
  5. ==============================

    5.오라클에 적어도 그들은 모두 동일합니다 http://www.oracledba.co.uk/tips/count_speed.htm

    오라클에 적어도 그들은 모두 동일합니다 http://www.oracledba.co.uk/tips/count_speed.htm

  6. ==============================

    6.나는 또 다른 하나의 DBMS의 성능 특성 변화를 느낍니다. 그것은 그들이 그것을 구현하기 위해 선택하는 방법에 대한 전부입니다. 내가 오라클에 광범위하게 일했기 때문에, 그 관점에서 말할 것이다.

    나는 또 다른 하나의 DBMS의 성능 특성 변화를 느낍니다. 그것은 그들이 그것을 구현하기 위해 선택하는 방법에 대한 전부입니다. 내가 오라클에 광범위하게 일했기 때문에, 그 관점에서 말할 것이다.

    COUNT는 (*) - 로우 null가 아닌 경우 카운트 함수에 전달하기 전에 결과 집합으로 전체 행을 가져오고, 함수는 1을 계산한다 집계

    COUNT (1) - 어떤 행을 인출하지 않음은, 대신 카운트는 경우 WHERE 일치 테이블의 각 행에 대해 1의 일정한 값이라고합니다.

    COUNT (PK) - 오라클의 PK 색인된다. 이것은 오라클은 인덱스를 읽을 수 있습니다 의미합니다. 일반적으로 인덱스 B의 + 트리에서 한 행은 실제 행보다 몇 배 작다. 그래서 디스크 IOPS 속도를 고려, 오라클은 전체 행에 비해 하나의 블록 전송과 많은 시간을 지수에서 더 많은 행을 가져올 수 있습니다. 쿼리의 높은 처리량이 리드.

    이로부터 첫 번째 카운트가 느린이며, 마지막 카운트가 오라클에서 가장 빠른 볼 수 있습니다.

  7. from https://stackoverflow.com/questions/2710621/count-vs-count1-vs-countpk-which-is-better by cc-by-sa and MIT license