where 절에 윈도우 기능이 없는 이유는 무엇입니까?
제목이 모든 것을 말해줍니다. 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이지만, 실제로는 where 절에서 윈도우 기능을 사용할 수 없는 이유를 찾고 있습니다.
SQL Server의 where 절에서 창 기능을 사용할 수 없는 이유는 무엇입니까?
특별한 정보를 제공하지는 않지만, 한 가지 대답은 사양서에 그럴 수 없다고 나와 있기 때문입니다.
Itzik Ben Gan의 기사 - 논리적 질의 처리: 그것이 당신에게 무엇을 의미하는지, 그리고 특히 여기에 있는 이미지.윈도우 기능은 다음 시간에 평가됩니다.SELECT
결국 남은 결과 세트에서.WHERE
/JOIN
/GROUP BY
/HAVING
조항이 처리되었습니다(5.1단계).
정말로 저는 windowing 기능을 사용할 수 없는 이유를 찾고 있습니다.
▁in▁▁that▁are▁에 들어갈 수 없는 이유.WHERE
조항은 모호성을 만든다는 것입니다.윈도우 기능을 이용한 고성능 T-SQL에서 Itzik Ben Gan의 사례 도용 (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'
서술어가 행 번호 매기기 전이나 후에 실행되었습니까?
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
절그래서 만약 당신이 그것을 사용하려고 합니다.row_number
순식간에WHERE
할당되지 . 이값 할아않 았습니 다지되 ▁clause니다 습▁the않 clause▁is았 ▁value▁yet값▁assigned.
창 기능에 미치는 영향 장:
다음이 있다고 가정합니다.
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;
All-at-Once 작업은 이 두 가지 조건이 동시에 논리적으로 평가된다는 것을 알려줍니다.따라서 SQL Server는 예상 실행 계획을 기준으로 WHERE 절의 조건을 임의의 순서로 평가할 수 있습니다.그래서 여기서 가장 중요한 문제는 어떤 조건이 먼저 평가되는지입니다.
사례 1:
If ( Id = 1002 ) is first, then if ( ROW_NUMBER() OVER(ORDER BY Id) = 1 )
결과: 1002
사례 2:
If ( ROW_NUMBER() OVER(ORDER BY Id) = 1 ), then check if ( Id = 1002 )
결과: 비어 있음
그래서 우리는 역설을 가지고 있습니다.
이 예는 WHERE 절에서 Window Functions를 사용할 수 없는 이유를 보여줍니다.이에 대해 더 자세히 생각해 보고 SELECT 및 ORDER BY 절에서만 Window Functions를 사용할 수 있는 이유를 찾을 수 있습니다!
부록
Teradata 지원 조항:
사용자 지정 검색 조건에 따라 이전에 계산된 순서 분석 기능의 결과를 필터링합니다.
SELECT Id
FROM #Test
WHERE Id = 1002
QUALIFY ROW_NUMBER() OVER(ORDER BY Id) = 1;
Qualificate는 HAVING이 집계 함수 및 GROUP BY 절에서 수행하는 작업을 창 함수로 수행합니다.
따라서 쿼리의 실행 순서에서 QENAL은 창 함수가 계산된 후 평가됩니다.일반적으로 SELECT 문의 절은 다음과 같은 순서로 평가됩니다.
부터
Where Group by Having Window QUALIFY Distinct Order by Limit
창 기능의 결과를 필터링합니다.QEALINE을 사용하려면 SELECT 목록 또는 QEALINE 절에 하나 이상의 창 기능이 있어야 합니다.
반드시 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
오래된 실타래지만, 주제에 표현된 질문에 구체적으로 답하도록 노력하겠습니다.
where 절에 윈도우 기능이 없는 이유는 무엇입니까?
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
절그러나 이러한 열은 다음과 같은 후속 절에 의해 참조될 수 있습니다.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단계(즉, 처리 후)FROM
,WHERE
,GROUP BY
그리고.HAVING
단계), 창 기능은 에서만 허용됩니다.SELECT
그리고.ORDER BY
쿼리의 절입니다.
참고로, 관계형 모델이 순서가 지정된 데이터를 처리하지 않더라도 창 기능은 여전히 관계형 계층의 일부입니다.결과는 다음과 같습니다.SELECT
5.1단계. 윈도우 기능은 여전히 관계형입니다.
또한 엄밀히 말하면 윈도우 기능이 허용되지 않는 이유는WHERE
조항은 모호성을 만들기 때문이 아니라 논리적 질의 처리가 어떻게 처리되는지에 대한 순서이기 때문입니다.SELECT
의술진에 있는 T-SQL
.
마지막으로 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
)
완성도를 위해 드리는 겁니다.
기본적으로 첫 번째 "WHERE" 절 조건은 sql에 의해 읽히고 동일한 열/값 ID가 테이블을 조사했지만 row_num=1에는 아직 없습니다.그러므로 그것은 작동하지 않을 것입니다.그렇기 때문에 괄호를 먼저 사용하고 그 다음에 WHERE 조항을 작성할 것입니다.
네, 안타깝게도 윈도우 기능을 할 때 SQL은 당신의 위치 서술어가 합법적일지라도 당신에게 화를 냅니다.선택 문에 값이 있는 액트 또는 중첩 선택을 한 다음 나중에 해당 값으로 CTE 또는 중첩 선택을 참조합니다.자체적으로 설명할 수 있는 간단한 예입니다.대용량 데이터 세트를 수행하는 데 있어 성능 문제가 발생할 경우 언제든지 temp table 또는 table variable로 이동할 수 있습니다.
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.
언급URL : https://stackoverflow.com/questions/13997177/why-no-windowed-functions-in-where-clauses
'programing' 카테고리의 다른 글
__init__()의 내부 변수와 외부 변수 간의 차이(클래스 및 인스턴스 속성) (0) | 2023.06.21 |
---|---|
일반적인 열거형의 정수 값을 가져옵니다. (0) | 2023.06.21 |
vba를 사용하여 단일 워크시트만 다른 워크북에 복사하는 방법 (0) | 2023.06.21 |
IIS7에서 작동하는 gzip 압축을 어떻게 얻을 수 있습니까? (0) | 2023.06.21 |
Nodejs 애플리케이션 오류: pm2 배포를 사용할 때 EADDRINUSE 바인딩 (0) | 2023.06.21 |