2012-07-20 3 views
2


고정 된 정밀도로 십진수 값을 저장하는 열이 거의없는 estimate_item 인 MySQL 테이블이 있습니다. 여기 내 테이블 구조가 있습니다.Mysql 또는 PHP의 십진수 정밀도 처리

TABLENAME : estimate_item

enter image description here

PHP를 사용하여 레코드를 검색하는 동안, 난 MySQL의의 기능을 사용하여 몇 가지 기본적인 계산을 할, 내가 사용하는 SQL 쿼리가 이것이다.

SELECT 
    COUNT(ei.item_id) as total_item, 
    SUM(ei.quantity) as total_quantity, 
    SUM(ei.number_of_carton) as total_carton, 
    SUM(ei.number_of_carton * ei.cbm_per_carton) as total_cbm, 
    SUM(ei.quantity * ei.cost) as total_cost, 
    SUM(ei.quantity * ei.rate) as total_rate, 
    e.commission_amount, 
    SUM(ei.quantity * ei.rate) + e.commission_amount as total_amount 
FROM 
    ai_estimate e 
LEFT JOIN 
    ai_estimate_item ei ON ei.estimate_id = e.id 
WHERE 
    ei.estimate_id = ? 

예를 들어 위의 쿼리는 결과를 반환합니다. 다음 열 이후

+------------+----------------+--------------+-----------+------------+------------+-------------------+--------------+ 
| total_item | total_quantity | total_carton | total_cbm | total_cost | total_rate | commission_amount | total_amount | 
+------------+----------------+--------------+-----------+------------+------------+-------------------+--------------+ 
|   2 |   120 |   807 | 1122.6440 |  2.7500 | 137.5000 |   1500.00 | 1637.5000 | 
+------------+----------------+--------------+-----------+------------+------------+-------------------+--------------+ 

내가 이런 식으로 네 열의 값을 반올림하려면, 4 개 정밀도 값 total_cbm_total, total_cost, total_rate, total_amount이 포함되어 있습니다.

a)의 값이 라운드 137.50

d는 다음 137.5000 경우 값) 그것이 라운드 2.75

℃로 다음 2.7500 경우 값) 그것이 라운드 1122.644

B를 다음 1122.6440이면) 값이 1200.0000 인 경우 반올림하여 1200.00

즉 값을 줄이려고합니다. 값에 따라 3 ~ 4 정밀도까지 올라갈 수있는 최소 2 개의 정밀도를 유지하십시오.

MySQL에서 직접이 작업을 수행 할 수있는 방법이 있습니까? 또는 PHP 방식?

감사합니다.

+0

을 기반으로

PHP 측이 여기에 당신이 찾고있는 무엇을 달성한다 난 그냥 해킹 간단한 함수입니다 예를 들어, 당신이 원하는 모든 후행 0을 자릅니다. PHP로 출력하고 싶다면, 문자열 조작이나 number_format 함수를 사용할 수 있습니다. – Lusitanian

+0

후행 0을 잘라내는 것이 문제가 될 수 있습니다.이 시점에서'1200.0000' 값을 갖고 있다면, 값이'1200.00'이되도록 두 개의 후행 0을 원합니까? –

답변

1

MySQL에서 그렇게한다면, 쿼리를 복잡하게 만들어서 CASE WHEN ... END를 추가해야 할 것입니다.

그래서 나는 PHP에서 그렇게 할 것입니다.

function reprecise($value) 
{ 
    $two_digit = number_format($value, 2); 
    $three_digit = number_format($value, 3); 
    return (float)$two_digit == (float)$three_digit ? $two_digit : $three_digit; 
} 

이것은 두 번째와 세 자리가있는 표현을 계산 한 다음 동일한 부동 숫자인지 확인합니다. 일치하는 경우 세 자리 버전의 마지막 숫자는 0이어야하며 대신 두 자리 버전이 사용됩니다.

당신이 할 수있는, 2, 3 또는 4 자리로 확장하려면 그주기에 :

function reprecise($value) 
{ 
    $digits = 9; 
    $base = strrev(number_format($value, $digits)); 
    for ($i = 0; $i < $digits-2; $i++) 
      if ($base[$i] != '0') 
        break; 
    return strrev(substr($base, $i)); 
} 
+0

좋은 방법. 물론 소수점 이하 자릿수가 증가함에 따라 점점 더 복잡해질 것입니다. 그대로, OP는 소수점 2, 3 또는 4를 다루고 있습니다. 당신이 2 ~ 10 자릿수 사이의 어디에서든지 외삽하면, 이것은 약간 악몽이 들게 될 것입니다. –

+0

참. 지금 답변을 편집 중입니다. 더 효율적인 방법은 최대 길이를 가진 문자열을 생성 한 다음 strrev()하고 최대 ($ digit-2) 개의 연속 0을 제거한 다음 다시 strrev()합니다. – LSerni

+0

잘 작동합니다. 감사합니다. –

1

: 문자열 함수로 number_format보다 더 빨리 될 가능성이 매우 높다 때문에

function reprecise($value) 
{ 
    $digits = 4; 
    for ($rep = number_format($value, $digits--); $digits >= 2; $digits--) 
    { 
      $new = number_format($value, $digits); 
      if ($new != $rep) 
        break; 
      $rep = $new; 
    } 
    return $rep; 
} 

또는, 한 가지 방법은 정규식을 사용하여 소수점 이하의 숫자 끝에있는 0을 모두 제거한 다음 소수 자릿수 2 자리 숫자를 형식화하고 두 결과를 비교하는 것입니다. 둘 중 가장 긴 것을 반환합니다 (문자열 방식).이것은 MySQL의에서 수행 할 수 있지만, 그것은 PHP에서 훨씬 쉬울 것 :

//$input - number to format 
//$num - minimum number of decimal places to keep 
function reformat($input, $num) { 
    $parse = preg_replace('/(\.[1-9]*)0+$/', "$1", $input); 
    $withmin = number_format($parse, 2); 
    return strlen($withmin) < strlen($parse) ? $parse : $withmin; 
} 
1

데이터베이스 측, 열 0 후행의 수 비용 것으로, 속도 및 cmb_per_carton이 테이블 구조에 의해 미리 정의되어 주목하는 귀하의 경우 4 0s :

cost DECIMAL 19,4 
rate DECIMAL 19,4 
cmb_per_carton DECIMAL 19,4 

이러한 필드로 작업을 수행하면 자연스럽게 같은 후행 0을 갖게됩니다.

function getDecimalFormatted($value, $minPrecision) { 
    $value = (float) $value; 
    return ((round((($value - floor($value))*pow(10, 5)))%1000) > 0) ? $value : number_format($value, $minPrecision, '.', ''); 
} 

사용 예 :

$value = "1234.71200"; 
echo getDecimalFormatted($value, 2)."\n<br>"; 

$value = "1234.70000"; 
echo getDecimalFormatted($value, 2)."\n<br>"; 

이 출력 :

1234.712 
1234.70