Home > Mobile >  How to convert easily metric values to imperial using SQL or Crystal Reports
How to convert easily metric values to imperial using SQL or Crystal Reports

Time:02-20

I'm using Crystal Reports 16 to generate reports for a customer and then use those reports in a software from another company. I'm not allowed to modify the database structure so I must do all data manipulation inside SQL Server's queries.

Most of the length in those reports are metric, but a few reports need a column with that length converted into imperial at 32th.

Here what I do in queries to convert those lengths

CASE
        WHEN a.PCE_LEN_FRACTION <= 16 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'
        WHEN a.PCE_LEN_FRACTION > 16 AND a.PCE_LEN_FRACTION <= 47 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 1/32'
        WHEN a.PCE_LEN_FRACTION > 47 AND a.PCE_LEN_FRACTION <= 79 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 1/16'
        WHEN a.PCE_LEN_FRACTION > 79 AND a.PCE_LEN_FRACTION < 110 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 3/32'
        WHEN a.PCE_LEN_FRACTION >= 110 AND a.PCE_LEN_FRACTION <= 141 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 1/8'
        WHEN a.PCE_LEN_FRACTION > 141 AND a.PCE_LEN_FRACTION < 172 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 5/32'
        WHEN a.PCE_LEN_FRACTION >= 172 AND a.PCE_LEN_FRACTION <= 204 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 3/16'
        WHEN a.PCE_LEN_FRACTION > 204 AND a.PCE_LEN_FRACTION < 235 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 7/32'
        WHEN a.PCE_LEN_FRACTION >= 235 AND a.PCE_LEN_FRACTION <= 266 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 1/4'
        WHEN a.PCE_LEN_FRACTION > 266 AND a.PCE_LEN_FRACTION < 297 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 9/32'
        WHEN a.PCE_LEN_FRACTION >= 297 AND a.PCE_LEN_FRACTION <= 329 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 5/16'
        WHEN a.PCE_LEN_FRACTION > 329 AND a.PCE_LEN_FRACTION < 360 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 11/32'
        WHEN a.PCE_LEN_FRACTION >= 360 AND a.PCE_LEN_FRACTION <= 391 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 3/8'
        WHEN a.PCE_LEN_FRACTION > 391 AND a.PCE_LEN_FRACTION < 422 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 13/32'
        WHEN a.PCE_LEN_FRACTION >= 422 AND a.PCE_LEN_FRACTION <= 454 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 7/16'
        WHEN a.PCE_LEN_FRACTION > 454 AND a.PCE_LEN_FRACTION < 485 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 15/32'
        WHEN a.PCE_LEN_FRACTION >= 485 AND a.PCE_LEN_FRACTION <= 516 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 1/2'
        WHEN a.PCE_LEN_FRACTION > 516 AND a.PCE_LEN_FRACTION < 547 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 17/32'
        WHEN a.PCE_LEN_FRACTION >= 547 AND a.PCE_LEN_FRACTION <= 579 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 9/16'
        WHEN a.PCE_LEN_FRACTION > 579 AND a.PCE_LEN_FRACTION < 610 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 19/32'
        WHEN a.PCE_LEN_FRACTION >= 610 AND a.PCE_LEN_FRACTION <= 641 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 5/8'
        WHEN a.PCE_LEN_FRACTION > 641 AND a.PCE_LEN_FRACTION < 672 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 21/32'
        WHEN a.PCE_LEN_FRACTION >= 672 AND a.PCE_LEN_FRACTION <= 704 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 11/16'
        WHEN a.PCE_LEN_FRACTION > 704 AND a.PCE_LEN_FRACTION < 735 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 23/32'
        WHEN a.PCE_LEN_FRACTION >= 735 AND a.PCE_LEN_FRACTION <= 766 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 3/4'
        WHEN a.PCE_LEN_FRACTION > 766 AND a.PCE_LEN_FRACTION < 797 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 25/32'
        WHEN a.PCE_LEN_FRACTION >= 797 AND a.PCE_LEN_FRACTION <= 829 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 13/16'
        WHEN a.PCE_LEN_FRACTION > 829 AND a.PCE_LEN_FRACTION < 860 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 27/32'
        WHEN a.PCE_LEN_FRACTION >= 860 AND a.PCE_LEN_FRACTION <= 891 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 7/8'
        WHEN a.PCE_LEN_FRACTION > 891 AND a.PCE_LEN_FRACTION < 922 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 29/32'
        WHEN a.PCE_LEN_FRACTION >= 922 AND a.PCE_LEN_FRACTION <= 954 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 15/16'
        WHEN a.PCE_LEN_FRACTION > 954 AND a.PCE_LEN_FRACTION < 985 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES as varchar)   '"'   ' 31/32'
        WHEN a.PCE_LEN_FRACTION >= 985 AND a.PCE_LEN_INCHES < 11 THEN
            CAST(a.PCE_LEN_FEETS as varchar)   ''' '   CAST(a.PCE_LEN_INCHES   1 as varchar)   '"'
        WHEN a.PCE_LEN_FRACTION >= 985 AND a.PCE_LEN_INCHES = 11 THEN
            CAST(a.PCE_LEN_FEETS  1 as varchar)   ''' 0"'
        ELSE ''
    END

It works ok for the amount of data I get from my query, but I use the same thing 4 times in a specific query.

In Crystal reports, I can't find any build-in founction to convert metric to imperial directly, which may improve performance much not having to do in into my query.

Does anyone know a more efficient way to convert metrics to imperials using SQL or Crystal Reports?

CodePudding user response:

If you first round to the nearest integral multiple of 1/32 inch, you can test for numerator divisible by 32, 16, 8, 4, and 2 to reduce your case statement down to a small handful. Each case would then calculate and format your fraction as wholes, halves, quarters, etc.

Having your fraction already separated from the whole and represented as 1/1000ths complicates things a bit, especially when handling the 32/32 round up case.

Below is an example that demonstrates two versions of a more compact fraction formatter with a range of generated data.

DECLARE @Data TABLE (
    Value Decimal(10,3),
    Inch INT,
    Thousands INT,
    ThirtySeconds INT,
    Carry INT,
    InchFraction VARCHAR(100),
    TotalThirtySeconds INT,
    InchFraction2 VARCHAR(100)
    )

-- Generate data from 0.950 thru 2.050
INSERT @Data (Value)
SELECT TOP 1101 (ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) - 1) / 1000.000   0.950
FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) D1(D)
CROSS JOIN (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) D2(D)
CROSS JOIN (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) D3(D)
CROSS JOIN (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) D4(D)

UPDATE @Data SET Inch = FLOOR(Value), Thousands = Value * 1000 % 1000

-- Calcuating from integer thousands to 32nds to fraction
UPDATE @Data SET ThirtySeconds = ROUND(Thousands * 32.0 / 1000, 0)
UPDATE @Data SET Carry = CASE WHEN ThirtySeconds = 32 THEN 1 ELSE 0 END
UPDATE @Data SET InchFraction = CONVERT(VARCHAR(10), Inch   Carry)
      CASE
      WHEN ThirtySeconds 2 = 0 THEN ''
      WHEN ThirtySeconds  = 0 THEN ' '   CONVERT(VARCHAR(10), ThirtySeconds / 16)   '/2'
      WHEN ThirtySeconds %8 = 0 THEN ' '   CONVERT(VARCHAR(10), ThirtySeconds / 8)   '/4'
      WHEN ThirtySeconds %4 = 0 THEN ' '   CONVERT(VARCHAR(10), ThirtySeconds / 4)   '/8'
      WHEN ThirtySeconds %2 = 0 THEN ' '   CONVERT(VARCHAR(10), ThirtySeconds / 2)   '/16'
      ELSE ' '   CONVERT(VARCHAR(10), ThirtySeconds)   '/32'
      END

-- Calculation direct from Value
UPDATE @Data SET TotalThirtySeconds = Round(Value * 32, 0)
UPDATE @Data SET InchFraction2 = CONVERT(VARCHAR(10), TotalThirtySeconds / 32)
      CASE
      WHEN TotalThirtySeconds 2 = 0 THEN ''
      WHEN TotalThirtySeconds  = 0 THEN ' '   CONVERT(VARCHAR(10), TotalThirtySeconds % 32 / 16)   '/2'
      WHEN TotalThirtySeconds %8 = 0 THEN ' '   CONVERT(VARCHAR(10), TotalThirtySeconds % 32 / 8)   '/4'
      WHEN TotalThirtySeconds %4 = 0 THEN ' '   CONVERT(VARCHAR(10), TotalThirtySeconds % 32 / 4)   '/8'
      WHEN TotalThirtySeconds %2 = 0 THEN ' '   CONVERT(VARCHAR(10), TotalThirtySeconds % 32 / 2)   '/16'
      ELSE ' '   CONVERT(VARCHAR(10), TotalThirtySeconds  % 32)   '/32'
      END

-- Show summary
SELECT FromValue = MIN(Value), ThruValue = MAX(Value), InchFraction, InchFraction2
FROM @Data
GROUP BY InchFraction, InchFraction2
ORDER BY MIN(Value)

-- Show details including intermediate values
SELECT *
FROM @Data
ORDER BY Value

Partial Results:

FromValue ThruValue InchFraction InchFraction2
0.950 0.953 0 15/16 0 15/16
0.954 0.984 0 31/32 0 31/32
0.985 1.015 1 1
1.016 1.046 1 1/32 1 1/32
1.047 1.078 1 1/16 1 1/16
1.079 1.109 1 3/32 1 3/32
1.110 1.140 1 1/8 1 1/8
1.141 1.171 1 5/32 1 5/32
1.172 1.203 1 3/16 1 3/16
1.204 1.234 1 7/32 1 7/32
Value Inch Thousands ThirtySeconds Carry InchFraction TotalThirtySeconds InchFraction2
0.950 0 950 30 0 0 15/16 30 0 15/16
0.953 0 953 30 0 0 15/16 30 0 15/16
0.954 0 954 31 0 0 31/32 31 0 31/32
0.984 0 984 31 0 0 31/32 31 0 31/32
0.985 0 985 32 1 1 32 1
0.999 0 999 32 1 1 32 1
1.000 1 0 0 0 1 32 1
1.015 1 15 0 0 1 32 1
1.016 1 16 1 0 1 1/32 33 1 1/32
1.046 1 46 1 0 1 1/32 33 1 1/32
1.047 1 47 2 0 1 1/16 34 1 1/16
1.078 1 78 2 0 1 1/16 34 1 1/16
1.079 1 79 3 0 1 3/32 35 1 3/32
1.099 1 99 3 0 1 3/32 35 1 3/32
1.100 1 100 3 0 1 3/32 35 1 3/32
1.109 1 109 3 0 1 3/32 35 1 3/32
1.110 1 110 4 0 1 1/8 36 1 1/8

See enter image description here

  • Related