어떤 경우에도 재고 당 행 수가 증가하는 데 도움이됩니다 (실제 quoteid
값은 실제로 도움이되지 않습니다). (이 표에서)을 캡처 한 것이 가장 쉽습니다. - 영업일뿐 아니라 주말/공휴일을 무시하는 등의 다른 작업을 원할 경우 더 많은 작업이 필요합니다. 달력 파일이 필요할 것입니다. [stockid
, createdate
]에 대한 색인이 아직없는 경우이를 원합니다. 제공된 데이터로부터 다음과 같은 결과가 산출
WITH StockRow AS (SELECT stockId, closePrice, createdDate,
ROW_NUMBER() OVER(PARTITION BY stockId
ORDER BY createdDate) rn
FROM Quote),
RunGroup AS (SELECT Base.stockId, Base.createdDate,
MAX(Restart.rn) OVER(PARTITION BY Base.stockId
ORDER BY Base.createdDate) groupingId
FROM StockRow Base
LEFT JOIN StockRow Restart
ON Restart.stockId = Base.stockId
AND Restart.rn = Base.rn - 1
AND Restart.closePrice > Base.closePrice)
SELECT stockId,
COUNT(*) AS consecutiveCount,
MIN(createdDate) AS startDate, MAX(createdDate) AS endDate
FROM RunGroup
GROUP BY stockId, groupingId
HAVING COUNT(*) >= 3
ORDER BY stockId, startDate
:
Increasing_Run
stockId consecutiveCount startDate endDate
===================================================
1 5 2012-01-01 2012-01-05
2 4 2012-01-01 2012-01-04
3 3 2012-01-02 2012-01-04
SQL Fiddle Example
은 (바이올린 또한, 복수의 런에 대한 일례를 가짐)이 분석 모든 갭을 무시
을 모든 실행에 정확하게 일치합니다 (다음에 양수 실행이 시작될 때).
그래서 어떻게 될까요?
StockRow AS (SELECT stockId, closePrice, createdDate,
ROW_NUMBER() OVER(PARTITION BY stockId
ORDER BY createdDate) rn
FROM Quote)
이 CTE
하나 개의 목적을 위해 사용되는 : 우리는 그래서 먼저 우리는 (날짜) 순서로 각 행 번호를, 다음/이전 행을 찾을 수있는 방법이 필요합니다 ...
RunGroup AS (SELECT Base.stockId, Base.createdDate,
MAX(Restart.rn) OVER(PARTITION BY Base.stockId
ORDER BY Base.createdDate) groupingId
FROM StockRow Base
LEFT JOIN StockRow Restart
ON Restart.stockId = Base.stockId
AND Restart.rn = Base.rn - 1
AND Restart.closePrice > Base.closePrice)
... 그런 다음 색인을 기준으로 합치십시오. LAG()
/LEAD()
을 가진 무언가를 얻는다면, 대신 그 대신에 더 나은 선택이 될 것입니다. 여기에는 중요한 한 가지가 있습니다. 행이 시퀀스 외 (이전 행보다 작음) 인 경우에만 일치가 발생합니다. 그렇지 않은 경우 값은 null
(LAG(), you'd need to use something like
CASE` 이후)이됩니다. 이 같은 형태의 임시 세트를 얻을 :
B.rn B.closePrice B.createdDate R.rn R.closePrice R.createdDate groupingId
1 15 2012-01-01 - - - -
2 13 2012-01-02 1 15 2012-01-01 1
3 17 2012-01-03 - - - 1
4 18 2012-01-04 - - - 1
5 10 2012-01-05 4 18 2012-01-04 4
을 ... 그래서 이전은 "현재"행보다 큰 경우에만 Restart
값이있다. window 함수에서 MAX()
의 사용은 지금까지 본 최대 값에 사용되었습니다 ... null
이 가장 낮기 때문에 다른 불일치가 발생할 때까지 다른 모든 행에 대해 행 색인이 유지됩니다 (새 값 제공) . 이 시점에서 우리는 본질적으로 gaps-and-islands 쿼리의 중간 결과를 가지며 최종 집계를 준비합니다.
SELECT stockId,
COUNT(*) AS consecutiveCount,
MIN(createdDate) AS startDate, MAX(createdDate) AS endDate
FROM RunGroup
GROUP BY stockId, groupingId
HAVING COUNT(*) >= 3
ORDER BY stockId, startDate
쿼리의 마지막 부분은 실행의 시작 및 종료 날짜를 얻고 해당 날짜 사이의 항목 수를 계산합니다. 날짜 계산에 좀 더 복잡한 것이 있다면, 아마도이 시점에서 일어날 필요가있을 것입니다. GROUP BY
은 이 아닌의 몇 가지 합법적 인 인스턴스 중 하나를 SELECT
절에 포함하여 표시합니다. HAVING
절은 "너무 짧음"실행을 제거하는 데 사용됩니다.
최소 길이의 연속 증가량을 하루 더 늘리시겠습니까? 또는 어떻게 든 그 감소에 의해 상쇄 되었습니까? 그리고 데이터가 있다면 여러 번 실행하고 싶다고 가정합니다. –
주말과 같이 데이터에 틈이 있습니까? 거기에서해야 할 일은 무엇입니까? –
연속 증가에 대한 규칙이 없으므로 전날보다 커야합니다. 네, 여러 번 달리고 싶습니다. 지난 3 개월, 6 개월의 데이터에 대해이 쿼리를 실행하거나 그 이상일 수 있습니다. 데이터에 차이가있을 수 있습니다, 우리는 전날 레코드를 가져 오기 위해 기본 키 열을 사용할 수 있습니다. –