복붙노트

[SQL] 왜 절 곳에서 함수, 윈도우를하지?

SQL

왜 절 곳에서 함수, 윈도우를하지?

내가 SQL Server에서 where 절에서 윈도우 기능을 사용할 수 없습니다 왜 제목은 모두 그것을 말한다?

이 쿼리는 완벽한 의미가 있습니다 :

select id, sales_person_id, product_type, product_id, sale_amount
from Sales_Log
where 1 = row_number() over(partition by sales_person_id, product_type, product_id order by sale_amount desc)

그러나 그것은 작동하지 않습니다. CTE를 / 하위 쿼리보다 더 좋은 방법이 있나요?

편집하다

어떻게 그 가치를 들면 이것은 CTE와 쿼리는 다음과 같습니다

with Best_Sales as (
    select id, sales_person_id, product_type, product_id, sale_amount, row_number() over (partition by sales_person_id, product_type, product_id order by sales_amount desc) rank
    from Sales_log
)
select id, sales_person_id, product_type, product_id, sale_amount
from Best_Sales
where rank = 1

편집하다

하위 쿼리와 함께 보여주는 답변 +1,하지만 정말 뒤에 추론을 찾고 있어요는 조항 곳에서 기능을 윈도 사용할 수없는.

해결법

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

    1.특히 유익한 것은 아니지만 사양은 당신이 할 수없는 것을 말한다 때문에 한 대답은,이다.

    특히 유익한 것은 아니지만 사양은 당신이 할 수없는 것을 말한다 때문에 한 대답은,이다.

    Itzik 벤 웨이 코 뮤니시에 의한 기사 참조 - 논리 질의 처리를 : 그것은이고 당신과 이미지 여기에 특히 무엇 그것은 무엇을 의미하는지. 윈도우 함수 / 조인 WHERE 모든 / GROUP BY가 / HAVING 절이 (단계 5.1)로 처리 한 후 남아있는 결과 세트에 SELECT시 평가된다.

    그들은 WHERE 절에서 허용되지 않습니다 이유는 모호성을 만들 것입니다. 윈도우 기능을 사용하여 고성능 T-SQL에서 Itzik 벤 웨이 코 뮤니시의 예를 훔치는 (P.25)

    테이블이었다 가정

    CREATE TABLE T1
    (
    col1 CHAR(1) PRIMARY KEY
    )
    
    INSERT INTO T1 VALUES('A'),('B'),('C'),('D'),('E'),('F')
    

    그리고 쿼리

    SELECT col1
    FROM T1
    WHERE ROW_NUMBER() OVER (ORDER BY col1) <= 3
    AND col1 > 'B'
    

    올바른 결과는 무엇일까요? 당신이 기대할 수있는 COL1이> 'B'술어 실행하기 전에 또는 행 번호 매기기 후?

  2. ==============================

    2.CTE, 그냥 서브 쿼리의 윈도 기능을 사용할 필요가 없습니다 :

    CTE, 그냥 서브 쿼리의 윈도 기능을 사용할 필요가 없습니다 :

    select id, sales_person_id, product_type, product_id, sale_amount
    from
    (
      select id, sales_person_id, product_type, product_id, sale_amount,
        row_number() over(partition by sales_person_id, product_type, product_id order by sale_amount desc) rn
      from Sales_Log
    ) sl
    where rn = 1
    

    편집 대답에 내 의견을 이동.

    데이터가 실제로 WHERE 절 뒤에있는 선택 될 때까지 윈도 함수가 수행되지 않는다. 당신이 값이 아직 할당되지 않은 WHERE 절에 ROW_NUMBER를 사용하려고한다면.

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

    3.우선 그것의 무언가를 한꺼번에 작업을 호출

    우선 그것의 무언가를 한꺼번에 작업을 호출

    그리고 윈도우 기능에 큰 장 영향 :

    당신이 가정 :

    CREATE TABLE #Test ( Id INT) ;
    
    INSERT  INTO #Test VALUES  ( 1001 ), ( 1002 ) ;
    
    SELECT Id
    FROM #Test
    WHERE Id = 1002
      AND ROW_NUMBER() OVER(ORDER BY Id) = 1;
    

    사례 1 :

    (ID = 1002) 제 경우, 만약 (ROW_NUMBER () OVER (ORDER BY 이드) = 1)

    결과 : 1002

    사례 2 :

    (ROW_NUMBER () OVER (ORDER BY 아이디) = 1), 다음 경우에 선택하면 (= 1002 Id)을

    결과 : 비어

    추가

    테라 데이타 지원 절 자격 :

    SELECT Id
    FROM #Test
    WHERE Id = 1002
    QUALIFY ROW_NUMBER() OVER(ORDER BY Id) = 1;
    

    부록 2 :

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

    4.당신은 반드시 CTE를 사용할 필요가 없습니다, 당신은) (ROW_NUMBER 사용 후 결과 세트를 조회 할 수 있습니다

    당신은 반드시 CTE를 사용할 필요가 없습니다, 당신은) (ROW_NUMBER 사용 후 결과 세트를 조회 할 수 있습니다

    select row, id, sales_person_id, product_type, product_id, sale_amount
    from (
        select
            row_number() over(partition by sales_person_id, 
                product_type, product_id order by sale_amount desc) AS row,
            id, sales_person_id, product_type, product_id, sale_amount
        from Sales_Log 
        ) a
    where row = 1
    
  5. ==============================

    5.마지막으로, 구식, 이전 SQL Server 2005의 방법은 상관 하위 쿼리와 함께있다 :

    마지막으로, 구식, 이전 SQL Server 2005의 방법은 상관 하위 쿼리와 함께있다 :

    select *
    from   Sales_Log sl
    where  sl.id = (
        Select Top 1 id
        from   Sales_Log sl2
        where  sales_person_id = sl.sales_person_id
           and product_type = sl.product_type
           and product_id = sl.product_id
        order by sale_amount desc
    )
    

    나는 단지 완전성을 위해서 당신이를 제공합니다.

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

    6.그것은 오래 된 스레드,하지만 내가 특별히 주제에 표현 된 질문에 대한 답변을 찾아보십시오.

    그것은 오래 된 스레드,하지만 내가 특별히 주제에 표현 된 질문에 대한 답변을 찾아보십시오.

    SELECT 문은 주문에서 키 입력에 지정된 주요 절을 다음과 같은있다 :

    SELECT DISTINCT TOP list
    FROM  JOIN ON / APPLY / PIVOT / UNPIVOT
    WHERE
    GROUP BY  WITH CUBE / WITH ROLLUP
    HAVING
    ORDER BY
    OFFSET-FETCH
    

    논리 질의 처리 주문, 또는 바인딩 주문, 그것은 쿼리의 정확성을 정의, 개념 해석의 순서입니다. 한 단계에서 정의 된 객체가 후속 단계의 절에 제공 할 때의 순서를 결정한다.

    ----- Relational result
      1. FROM
        1.1. ON JOIN / APPLY / PIVOT / UNPIVOT
      2. WHERE
      3. GROUP BY
        3.1. WITH CUBE / WITH ROLLUP
      4. HAVING
      ---- After the HAVING step the Underlying Query Result is ready
      5. SELECT
        5.1. SELECT list
        5.2. DISTINCT
    ----- Relational result
    
    ----- Non-relational result (a cursor)
      6. ORDER BY
      7. TOP / OFFSET-FETCH
    ----- Non-relational result (a cursor)
    

    쿼리 프로세서가 FROM 절에 정의 (액세스) 테이블이나 뷰에 바인딩 할 수 있습니다 예를 들어, 이러한 개체 및 열 이후의 모든 단계를 사용할 수 있습니다.

    반대로, SELECT 절 선행 모든 조항 SELECT 절에 정의 된 컬럼 alias 또는 유도 열을 참조 할 수있다. 그러나 이러한 열은 같은 ORDER BY 절로서 다음 절을 참조 할 수 있습니다.

    관련된 윈도우 함수가 적용되기 전에 OVER 절은 행 세트의 분할 및 순서를 결정한다. 즉, OVER 절을 계산하여 그 결과 창에 대 기초 쿼리 결과 세트의 창 함수 내의 행 창 또는 사용자 지정 세트를 정의한다.

    Msg 4108, Level 15, State 1, …
    Windowed functions can only appear in the SELECT or ORDER BY clauses.
    

    이유는 뒤에 논리 질의 처리는 T-SQL에서 어떻게 작동 방식 때문이다. 논리 질의 처리는 SELECT 단계 5.1에 도달 할 경우에만 기본 쿼리 결과 때문에 설정된다. (즉,로부터 처리 후 GROUP BY 갖는 단계 임), 윈도우 함수는 질의의 절하여 SELECT 및 ORDER에서만 허용된다.

    언급에 참고, 윈도우 함수는 여전히 심지어 관계형 모델은 주문 데이터를 처리하지 않는 관계형 층의 일부입니다. 선택 (SELECT) 5.1 단계 후의 결과. 모든 창 기능을 여전히 관계형이다.

    또한, 엄밀히 말하면, 윈도우 함수는 WHERE 절에서 허용되지 않는 이유는 모호성을 만들 수 있지만 때문없는 논리 질의 처리는 T-SQL에서 SELECT 문을 처리하는 방법을 순서 때문이다.

    링크 : 여기, 여기와 여기에

  7. ==============================

    7.기본적으로 제 "WHERE"절의 조건 SQL 테이블로하지만 테이블 ROW_NUM = 1 보였다 동일한 열 / 값 ID로 판독 아직있다. 따라서이 작동하지 않습니다. 이유 그게 전부 우리는 먼저 괄호를 사용하고 그 후 우리는 WHERE 절을 작성합니다.

    기본적으로 제 "WHERE"절의 조건 SQL 테이블로하지만 테이블 ROW_NUM = 1 보였다 동일한 열 / 값 ID로 판독 아직있다. 따라서이 작동하지 않습니다. 이유 그게 전부 우리는 먼저 괄호를 사용하고 그 후 우리는 WHERE 절을 작성합니다.

  8. ==============================

    8.당신은 윈도우 기능을 수행 할 때 예 불행하게도 SQL은 술어가 합법적 인 사용자입니다 경우에도 화를 가져옵니다. 당신은 CTE를하거나 다음 CTE 참조하거나 나중에 값을 선택 중첩, 당신의 선택 문에서 값을 갖는 선택 중첩. 자기 설명해야합니다 간단한 예. 당신이 정말로 큰 데이터를하고 몇 가지 성능 문제에 대한 CTE의 미워하면 당신은 항상 임시 테이블이나 테이블 변수에 놓을 수 있습니다 설정합니다.

    당신은 윈도우 기능을 수행 할 때 예 불행하게도 SQL은 술어가 합법적 인 사용자입니다 경우에도 화를 가져옵니다. 당신은 CTE를하거나 다음 CTE 참조하거나 나중에 값을 선택 중첩, 당신의 선택 문에서 값을 갖는 선택 중첩. 자기 설명해야합니다 간단한 예. 당신이 정말로 큰 데이터를하고 몇 가지 성능 문제에 대한 CTE의 미워하면 당신은 항상 임시 테이블이나 테이블 변수에 놓을 수 있습니다 설정합니다.

    declare @Person table ( PersonID int identity, PersonName varchar(8));
    
    insert into @Person values ('Brett'),('John');
    
    declare @Orders table ( OrderID int identity, PersonID int, OrderName varchar(8));
    
    insert into @Orders values (1, 'Hat'),(1,'Shirt'),(1, 'Shoes'),(2,'Shirt'),(2, 'Shoes');
    
    --Select
    --  p.PersonName
    --, o.OrderName
    --, row_number() over(partition by o.PersonID order by o.OrderID)
    --from @Person p 
    --  join @Orders o on p.PersonID = o.PersonID
    --where row_number() over(partition by o.PersonID order by o.orderID) = 2
    
    -- yields:
    --Msg 4108, Level 15, State 1, Line 15
    --Windowed functions can only appear in the SELECT or ORDER BY clauses.
    ;
    
    with a as 
        (
        Select
        p.PersonName
    ,   o.OrderName
    ,   row_number() over(partition by o.PersonID order by o.OrderID) as rnk
    from @Person p 
        join @Orders o on p.PersonID = o.PersonID
        )
    select *
    from a 
    where rnk >= 2 -- only orders after the first one.
    
  9. from https://stackoverflow.com/questions/13997177/why-no-windowed-functions-in-where-clauses by cc-by-sa and MIT license