MySQL에서 누계 계산
이 MySQL 쿼리가 있습니다.
SELECT DAYOFYEAR(`date`) AS d, COUNT(*)
FROM `orders`
WHERE `hasPaid` > 0
GROUP BY d
ORDER BY d
다음과 같은 결과를 반환합니다.
d | COUNT(*) |
20 | 5 |
21 | 7 |
22 | 12 |
23 | 4 |
내가 원하는 것은 마지막에 누계를 표시하는 또 다른 열입니다.
d | COUNT(*) | ??? |
20 | 5 | 5 |
21 | 7 | 12 |
22 | 12 | 24 |
23 | 4 | 28 |
이것이 가능한가?
당신에게 더 간단한 솔루션이 될 데이터베이스가 많은 쿼리를 수행 할 수 있습니다. 이것은 하나의 쿼리 만 실행 한 다음 단일 패스에서 결과에 대해 약간의 수학을 수행합니다.
SET @runtot:=0;
SELECT
q1.d,
q1.c,
(@runtot := @runtot + q1.c) AS rt
FROM
(SELECT
DAYOFYEAR(`date`) AS d,
COUNT(*) AS c
FROM `orders`
WHERE `hasPaid` > 0
GROUP BY d
ORDER BY d) AS q1
그러면 추가 RT (누계) 열이 제공됩니다. 누계 변수를 초기화하기 위해 맨 위에있는 SET 문을 놓치지 마세요. 이름은 NULL 값의 열을 존재합니다.
SELECT
DAYOFYEAR(O.`date`) AS d,
COUNT(*),
(select count(*) from `orders`
where DAYOFYEAR(`date`) <= d and `hasPaid` > 0)
FROM
`orders` as O
WHERE
O.`hasPaid` > 0
GROUP BY d
ORDER BY d
이 약간의 구문 조정이 필요하지만 (나는 그것을 테스트 할 MySQL이 없습니다), 당신에게 아이디어를 보여줍니다. 하위 쿼리는 다시 돌아가서 외부 쿼리에 이미 포함 된 모든 새로운 항목을 추가해야하며 모든 행에 대해 수행해야합니다.
에서보세요이 질문 사용하는 방법에 대한이 같은 달성하기 위해 섭니다.
증가하는 데이터로 인한 성능 문제를 해결 비용 : 1 년에 366 일이고 여러 해에 대해 쿼리를 실행하지 않는다고 가정하면 하위 쿼리가 최대 366 번 평가됩니다. 날짜에 대한 정책과 hasPaid 플래그가 괜찮을 것입니다.
MySQL 8부터는 다음과 같은 쿼리에 창 함수 를 사용 합니다.
SELECT dayofyear(`date`) AS d, count(*), sum(count(*)) OVER (ORDER BY dayofyear(`date`))
FROM `orders`
WHERE `hasPaid` > 0
GROUP BY d
ORDER BY d
위의 쿼리에서 집계 함수 count(*)
는 윈도우 함수 내부에 중첩되어 sum(..) OVER (..)
있는데, 이는 SQL 의 논리적 연산 순서로 인해 가능합니다 . 너무 혼란 스러우면 파생 테이블이나 WITH
절 을 사용하여 쿼리를 더 잘 구성 할 수 있습니다.
WITH daily (d, c) AS (
SELECT dayofyear(`date`) AS d, count(*)
FROM `orders`
WHERE `hasPaid` > 0
GROUP BY d
)
SELECT d, c, sum(c) OVER (ORDER BY d)
ORDER BY d
모든 결과 행이 독립적이어야하는 것은 불가능하다고 말하고 싶습니다. 이러한 값을 얻기 위해 프로그래밍 언어 사용
다른 옵션이 없지만 SQL에서 수행하지 않는 한 쿼리를 작성하는 프로그래밍 언어로 결과를 합산합니다. 이와 같은 중첩은 테이블이 커짐에 따라 매우 느려집니다.
Cross Join 문이나 일부 slef 조인을 사용하여이를 해킹 할 수 있지만 큰 데이터 세트에서는 속도가 느려지므로 아마도 사후 쿼리 프로세서에서 수행하는 것이 가장 좋습니다. 클라이언트 코드의 커서
성능이 중요하다면 커서가 집합 기반 쿼리보다 빠른 유일한 위치 중 하나입니다.
- MySql 외부에서 수행하거나
- MySql 5 커서 사용
MySQL의 임시 테이블을 사용하여 러닝 밸런스를 계산할 수 있습니다. 다음 쿼리가 작동해야합니다.
CREATE TEMPORARY table orders_temp1 (SELECT id, DAYOFYEAR(`date`) AS d, COUNT(*) as total FROM `orders` WHERE `hasPaid` > 0 GROUP BY d ORDER BY d);
CREATE TEMPORARY table orders_temp2 (SELECT * FROM orders_temp1);
SELECT d, total, (SELECT SUM(t2.total) FROM orders_temp2 t2 WHERE t2.id<=t1.id) as running_total FROM orders_temp1 t1;
쿼리를 구성하는 데 임시 테이블이 사용됩니다. 임시 테이블은 MySQL 서버에 연결하는 동안 만 존재합니다.
위 쿼리는 현재 행을 포함하여 임시 테이블에있는 모든 행의 잔액을 반환하는 하위 쿼리를 사용합니다. 잔액은 실제 테이블의 현재 행에 할당됩니다.
참조 URL : https://stackoverflow.com/questions/664700/calculate-a-running-total-in-mysql
'ProgramingTip' 카테고리의 다른 글
전화 및 Callvirt (0) | 2020.12.29 |
---|---|
파일 / 디렉토리의 내용을 모니터링 하시겠습니까? (0) | 2020.12.29 |
읽기 메모리 장벽과 인증서를 이해하는 방법 (0) | 2020.12.29 |
Java에서 제네릭 유형 인스턴스화 (0) | 2020.12.29 |
증가 / 누름시 ImageButton의 축적을 변경하는 방법 (0) | 2020.12.29 |