openlang

총합이 합계가 아니라 숫자가 그냥 붙어서 출력돼요

일별 줄은 멀쩡한데(12500, 3400, 900원), TOTAL은 0125003400900 KRW로 찍혀요. 왜 0이 하나 더 붙죠?

const grand = rows.reduce((acc, r) => acc + r.cents, 0);
console.log(`TOTAL ${won(grand)}`);

tsc는 통과하고, Postgres 16은 docker에서 돌려요. reduce는 늘 쓰던 그대로인데요...

영어에서 번역원문 보기

이어지는 대화 10

서로의 근거를 따라
  1. 고유 링크

    cents가 bigint나 numeric 컬럼인가요? 드라이버가 그런 값은 문자열로 돌려주는데, 0 + "12500"은 "012500"이에요. tsc는 그걸 못 봐요.

    영어에서 번역원문 보기
  2. 고유 링크

    네, 거의 확실히 그거예요. 0125003400900은 그냥 문자열이 이어 붙은 거고, pg는 bigint와 numeric을 문자열로 돌려줘요. reduce에서 Number(r.cents)를 쓰거나, 값이 들어간다면 쿼리에서 cents::int로 캐스팅하면 돼요. 값이 커질 수 있으면 BigInt를 쓰고 마지막에 포맷하세요.

    영어에서 번역원문 보기
  3. 고유 링크

    잘못된 건 없어요, 합계가 그냥 아주 정직할 뿐이에요. Postgres는 텍스트를 보내고, JavaScript는 그걸 이어 붙여요. 문자열 이어 붙이기로 하는 회계인데 tsc는 "괜찮아 보이는데요"래요. 그럴 만하죠.

    영어에서 번역원문 보기
  4. 고유 링크

    cents::int에 주의할 점이 하나 있어요. 대신 SQL에서 합계를 내면 결과가 다시 문자열이에요. sum(int)는 bigint를, sum(bigint)는 numeric을 반환하고, 드라이버는 둘 다 텍스트로 줘요. 그러니 어차피 Number()는 필요하고, 행마다 하는 대신 마지막에 한 번만 하면 돼요.

    그래도 쿼리에서 합계를 내는 게 더 나은 방법이에요. 데이터베이스가 한 번에 처리해 주니까요. 집계 함수의 반환 타입은 Postgres 집계 함수 문서에 나와 있어요.

    영어에서 번역원문 보기
  5. 고유 링크

    웃긴 건 won()이 문자열 "12500"도 숫자랑 똑같이 포맷해서 일별 줄은 괜찮아 보였다는 거예요. +에서만 드러났어요. 그리고 앞의 0은 제 초기값 0이 텍스트가 된 거였고요. MDN의 덧셈 연산자 페이지에 분명히 나와 있어요, 한쪽이라도 문자열이면 이어 붙인다고요. 알고는 있었는데, reduce 안에서는 처음이라...

    영어에서 번역원문 보기

같은 질문의 다른 갈래

  1. 에러 없이 끝난 rows.Next 루프

    database/sql로 만든 작은 도구가 목록을 반만 돌려줬어. 에러 없이. 코드는 이래. 컨텍스트에 데드라인이 있었어. 가져오는 도중에 데드라인이 지나서 rows.Next()가 false를 줬고, 루프가 끝났고, 함수는…

    답글 3최근 활동 sqlgo
  2. partial index와 WHERE 절의 파라미터

    수업 프로젝트로 Go로 작은 job runner를 만들고 있어요. 환경은 database/sql을 통해 쓰는 pgx v5, 로컬 Postgres 16이고, jobs 테이블에 행이 600만 개쯤 있어요. 거의 다 done이고…

    답글 10최근 활동 sqlgo
  3. SKIP LOCKED 작업 큐, 트랜잭션 도중에 워커가 죽으면

    작업 큐를 그냥 테이블에 둠. 워커 하나는 Python, 하나는 Go. BEGIN, 그다음 SELECT id, payload FROM jobs WHERE status = 'queued' ORDER BY id LIMIT 1 F…

    답글 5최근 활동 sqlgo