2015-01-13 3 views
0

나는 주차 계량기의 실시간 데이터를 얻었으며 주차 계좌의 현재 상태를 과거 데이터와 비교하고자합니다. 내 데이터에는 주차 티켓이 포함되어 있습니다. 주차 티켓은 구입 당시의 datetime_start 및 더 이상 유용하지 않은 datetime_stop을 포함합니다.주차 계좌 거래 내역 데이터와 비교

이 SQL은 실제로 작동하지만 매우 느립니다. 나는 어떻게 든 최적화 할 수있는 몇 번이나 다른 것들에 대한 모든 데이터를 통해 실행 같아요

(SELECT "parking_meter_id", SUM(CASE WHEN Now() BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) < ( 
SUM(CASE WHEN Now() - interval '1 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '2 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '3 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '4 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '5 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '6 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '7 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '8 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) 
/8) AS available 
FROM "parking_meter_transactions" 
WHERE 
Now() BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '1 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '2 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '3 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '4 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '5 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '6 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '7 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '8 week' BETWEEN "datetime_start" AND "datetime_stop" 
GROUP BY "parking_meter_id") AS transactions 

기본적인 아이디어는 지금 (현재의 "법적"입니다 티켓의 양)을 계산하고 비교하는 것입니다 같은 시간대에 지난 8 주 동안의 금액으로 계산됩니다. 이것은 가능한 주차 공간이 있어야하는지에 대한 통계적 아이디어를 줄 수 있습니다.

+0

WHERE 절이 8 대신 16 주를 표시하는 이유는 무엇입니까? –

+0

datetime_start 및 datetime_stop은 모두 큰 따옴표 (대)로 묶어야합니다. 원래의 질문을 편집하여 데이터 샘플을 보여주는 것이 더 좋을 수도 있습니다. 그리고 공간 정렬과 탭 정렬을 통해 가독성을 높이십시오. – DRapp

+0

@DRapp : 열 이름과 같은 식별자는 큰 따옴표 또는 따옴표를 사용하지 않습니다. 그들은 작은 따옴표를 사용하지 않습니다. –

답변

1

내가

(datetime_start, datetime_stop, parking_meter_id) 

이 방법을 기반으로 쿼리에 대한 커버링 인덱스를 작성 제안, 데이터베이스 쿼리를 완료하기 위해 원시 데이터 페이지로 이동 할 필요가 없습니다.

또한 WHERE 절을 단일 날짜 비교 범위로 매우 단순하게 조정하십시오. 당신의 SUM에서 (케이스) 블록은, 그래, 당신은()가 적용하지만 WHERE 절은 당신 "... 지금 생각해

WHERE datetime_start > Now() - interval '2 months' 

같은 것을 아래로 단순화 할 수있는 주를 구별 할 필요가 "전화는 무엇이든간에 ... 웃음 소리에 대해 Jan 1 @ 12:00 AM이라고 가정 해 봅시다. 때문에 모든 조항은 "OR"함께있는 WHERE

Now - 2 months = Week of Nov 13 
Now - 2 months - 1 week = Week of Nov 20 
Now - 2 months - 2 weeks = Week of Nov 27 
... 
Now - 2 months - 8 weeks = Brings us back to Now... 

그래서 NET 기간이 시작 날짜/시간이 2보다 큰 개월 전 아무것도입니다.

그렇다면 제안 된 색인은 성능을 크게 향상시켜야한다고 말했습니다. WHERE 절의 복잡성을 살펴보면 날짜 간격 (각 간격)을 계속 계산해야합니다. 색인을 효율적으로 활용할 수 없기 때문에 색인에 질식 할 가능성이 높습니다.

색인에 meter ID가 있으면 GROUP BY 절이 최적화됩니다.

의견 당 FEEDBACK

모든 날짜가 FARTHEST (지금) (2 개월)로 감싸 져 있습니다. 그 전에 아무것도 고려하지 마라. 그러나 지금 나는 당신에게 단지 8 주 동안의 주간의 시간에 특별한 "NOW()"표를 원한다라고하는 추가 절을 본다. 따라서 where 절은 단 하나의 조건에서 여전히 validd입니다.

복잡한 WHERE 조건을 적용하지 않고 엔진이 해당 날짜/시간의 모든 레코드를 전달하도록하십시오. SUM (CASE/WHEN)을 통한 COLUMN SELECTION은 해당 기간의 "Legel"을 기준으로 계산됩니다.

SUM (CASE WHEN 이제() - 간격 "datetime_start"BETWEEN '일주'AND THEN "datetime_stop"ELSE 1 0 END) + SUM (CASE WHEN 이제() - "datetime_start"간의 간격 '이주' AND "datetime_stop"THEN 1 ELSE 0 END) +

오후 2시 53 분과 같은 것을 찾고 있고 datetime_start 오후 7시 59 분에 1 월 2 일의 해당 WHERE 절 레코드가있는 경우 모든 CASE/WHEN 인스턴스에서 실패하고 결과 열의 NONE에 1이 추가되어 무시됩니다.

따라서 지난 2 개월 동안 기록이 10 건이 있더라도 색인을 통해 빠르게 이동하십시오. 귀하의 케이스/언제 당신이 찾고있는 2 월 53 일 (예 : :) 시간에만 한정된 것으로 간주되며 모든 주 기간에 314 개의 항목이 포함될 수 있습니다. 예 :

Wed, Jan 14 @ 2:53 
    Wed, Jan 7 @ 2:53 
    Wed, Dec 31 @ 2:53 
    Wed, Dec 24 @ 2:53 
    Wed, Dec 17 @ 2:53 
    Wed, Dec 10 @ 2:53 
    Wed, Dec 3 @ 2:53 
    Wed, Nov 26 @ 2:53 
    Wed, Nov 19 @ 2:53 
+0

내일 내 where 절을 편집하고 답변으로 돌아갑니다. 나의 첫 번째 선택 이유는 사용 된 것만 선택하는 것이 었습니다. 지난 2 개월 동안 모든 기록을 선택하면 원하는 비교 사이에 기록을 얻습니다. 이해가 되니? 그러나 아마도 더 복잡하고 느린 것보다 빠릅니다. – Henrik

+0

@ (datetime_start, datetime_stop)에 인덱스가 있고 (parking_meter_id)에 인덱스가 있습니다. – Henrik

+0

@Henrik, 별도의 인덱스를 이해하고 있지만, 하나만 사용하면 엔진을 사용할 알 필요가 없습니다. 날짜 별 및 주차 미터기 ID는 원시 데이터로 이동하지 않고 전체 쿼리를 해결할 수 있습니다. – DRapp