2017-03-20 1 views
7

저는 CTE와 관련하여 정확한 로직을 얻으려고 애 쓰고 있습니다.CTE 행 번호 파티셔닝

배경 정보 :

작업이 판매 역할이 모든 구성원에 대해 시스템에서 생성됩니다. 기본적으로 내 Task 테이블에 여러 레코드를 삽입합니다. 작업 탭에는 다음과 같은 열이 있습니다. AssignedToRequestedBy - AssignedTo에는 각 판매원 ID가 있습니다. 아무도 그것을 주장하지 않았기 때문에 현재 모든 판매 사람들은 작업을 볼 수

이제 작업이 각 판매 사람, 그 중 하나는에 반응 할 수, 중요하지 않습니다에 대해 생성 된 것을
ApprovalStatusId EntityType  EntityId AssignedTo  RequestedBy 
18    | FooBar  | 281  | 4    | 6 
18    | FooBar  | 281  | 9    | 6 
18    | FooBar  | 281  | 17   | 6 
18    | FooBar  | 281  | 26   | 6 
18    | FooBar  | 281  | 39   | 6 

작업 상태뿐만 아니라 AssignedTo 변경됩니다 작업 :

ApprovalStatusId EntityType EntityId AssignedTo RequestedBy 
18    | FooBar  | 281  | 4   | 6 
18    | FooBar  | 281  | 9   | 6 
18    | FooBar  | 281  | 17  | 6 
18    | FooBar  | 281  | 26  | 6 
18    | FooBar  | 281  | 39  | 6 
17    | FooBar  | 281  | 26  | 6 
1    | FooBar  | 281  | 6   | 6 

당신이 위의 표에서 볼 수있는 바와 같이, 사용자 (26)는 작업에 반응하고 상태를 변경했습니다. 이 작업이 완료되면 시스템은 작업 6을 사용자 6 인 원래의 요청으로 되돌려 보냈습니다. 상태도이 작업을 나타내도록 변경되었습니다.

문제 :

사람 : 현재

  1. , 한 사용자 (ID 4) 나는 무엇을 시도했다 모든 판매 사용자

에 할당 된 작업을보고 주소 1 :

;WITH cte AS 
(
    SELECT task.*, stat.Name AS StatusName, 
     ROW_NUMBER() OVER (PARTITION BY EntityId, EntityType ORDER BY ModifiedData DESC) AS rn 
    FROM dbo.Task task 
    INNER JOIN dbo.ApprovalStatus stat on task.ApprovalStatusId = stat.ApprovalStatusId 
) 

SELECT * 
FROM cte  
WHERE AssignedTo = @resourceId 
AND StatusName like 'Pending%' 
AND rn = 1 

이 SQL의 문제 중 하나는 AND rn = 1입니다. 이것이 포인트 1에서 제기 된 문제의 원인이지만, 제거하고 상태가 변경되면 최신 태스크 항목을 가져올 수 없기 때문입니다. 한편,이 문제도 발생합니다.

또한 파티셔닝을 PARTITION BY EntityId, EntityType, AssignedTo ORDER BY ModifiedData DESC으로 변경하려고했으나 대부분의 경우 rn이 1이되어 판매를 기반으로 올바른 결과를 산출하지 못합니다. 그룹.

[업데이트] :

작업 테이블 정의 : enter image description here

샘플 데이터 :

Comments  InsertDate      ModifiedData    CommentUserId ApprovalStatusId EntityType  EntityId  TenantId AssignedTo RequestedBy 
...   | 2017-03-20 11:18:06.343| 2017-03-20 11:18:06.343| NULL   | 18    | FooBar  | 75  |7    |4    |42 
...   | 2017-03-20 11:18:06.343| 2017-03-20 11:18:06.343| NULL   | 18    | FooBar  | 75  |7    |6    |42 
...   | 2017-03-20 11:18:06.343| 2017-03-20 11:18:06.343| NULL   | 18    | FooBar  | 75  |7    |9    |42 
...   | 2017-03-20 11:18:06.343| 2017-03-20 11:18:06.343| NULL   | 18    | FooBar  | 75  |7    |17    |42 
...   | 2017-03-20 11:18:06.343| 2017-03-20 11:18:06.343| NULL   | 18    | FooBar  | 75  |7    |26    |42 
...   | 2017-03-20 11:18:06.343| 2017-03-20 11:18:06.343| NULL   | 18    | FooBar  | 75  |7    |39    |42 
...   | 2017-03-20 11:18:06.343| 2017-03-20 11:18:06.343| NULL   | 18    | FooBar  | 75  |7    |67    |42 
...   | 2017-03-20 11:18:06.343| 2017-03-20 11:18:06.343| NULL   | 18    | FooBar  | 75  |7    |10073   |42 
...   | 2017-03-20 11:18:06.343| 2017-03-20 11:18:06.343| NULL   | 18    | FooBar  | 75  |7    |10164   |42 

원하는 출력 : 작업이 유일해야한다 주장

판매 사용자 그것을 볼 수있는 사람.즉, 판매, 사용자가 (두 번째 테이블의 예에서 볼 수)이 기록을 볼 수 있어야합니다 - 다른 모든 판매 사용자가 아무것도 나오지 않습니다

17    | FooBar  | 281  | 26  | 6 
+0

여기서 작업하는 전체 스키마 및 일부 테스트 데이터를 추가 할 수 있습니까? 귀하의 질문은 - 예를 들어 - 샘플 데이터의 어디에서나 'ModifiedData' 열을 가지고 있지 않습니다. 설명하기보다는 샘플 데이터를 기반으로 원하는 출력을 추가하십시오. – iamdave

+0

헤이 @iamdave, 답장을 보내 주셔서 감사합니다. 솔직히 말하면, 그것은 상당히 복잡합니다, 그래서 제가 할 수있는 최선을 다하려고 노력할 것입니다. –

+0

여기에 나오는 모든 날짜 값이 어떻게 같습니까? 이 부분이 오타가 아닌가? – iamdave

답변

2

당신이 원하는 결과를 보였다 경우 귀하의 질문은, 더 나은 것하지만, 나는 여러 레코드가 처음에 task 테이블에 삽입 할 때 당신이 대신 CTE가 반환하는 row_number() 이외의 다른 ranking 윈도우 함수와 같은 dense_rank()

;WITH cte AS 
(
    SELECT task.*, stat.Name AS StatusName, 
     dense_rank() OVER (PARTITION BY EntityId, EntityType ORDER BY ModifiedData DESC) AS dr 
    FROM dbo.Task task 
    INNER JOIN dbo.ApprovalStatus stat on task.ApprovalStatusId = stat.ApprovalStatusId 
) 

SELECT * 
FROM cte  
WHERE AssignedTo = @resourceId 
AND StatusName like 'Pending%' 
AND dr = 1 

사용을 고려한다 수행 할 수 있습니다 어떻게 생각 :

+------------------+------------+----------+------------+-------------+----+ 
| ApprovalStatusId | EntityType | EntityId | AssignedTo | RequestedBy | rn | 
+------------------+------------+----------+------------+-------------+----+ 
|    18 | FooBar  |  281 |   4 |   6 | 1 | 
|    18 | FooBar  |  281 |   9 |   6 | 2 | 
|    18 | FooBar  |  281 |   17 |   6 | 3 | 
|    18 | FooBar  |  281 |   26 |   6 | 4 | 
|    18 | FooBar  |  281 |   39 |   6 | 5 | 
+------------------+------------+----------+------------+-------------+----+ 

그것은 반환 :

+------------------+------------+----------+------------+-------------+----+ 
| ApprovalStatusId | EntityType | EntityId | AssignedTo | RequestedBy | dr | 
+------------------+------------+----------+------------+-------------+----+ 
|    18 | FooBar  |  281 |   4 |   6 | 1 | 
|    18 | FooBar  |  281 |   9 |   6 | 1 | 
|    18 | FooBar  |  281 |   17 |   6 | 1 | 
|    18 | FooBar  |  281 |   26 |   6 | 1 | 
|    18 | FooBar  |  281 |   39 |   6 | 1 | 
+------------------+------------+----------+------------+-------------+----+ 

그래서 그 사용자의 하나가 보류중인 작업을보고있는 문제점 # 1를 해결합니다.

+0

거룩한 담배 ... 'dense_rank()'에 대해 전혀 알지 못함 - 구현할 때 바쁨으로 점검 할 수 있는지 - 감사합니다. –

+0

@RichardBailey 도와 드리겠습니다! – SqlZim