How to get total weight of a case size e.g. 12 x 160g equal to 1.92kg

若如初见. 提交于 2021-02-16 23:43:13

问题


Not sure if this is possible.

But, let's say I have a column like this in a table:

12 x 60g
12 x 160g
500g
1kg
1kg
12 x 160g
12 x 250g

Some are are individual sizes and some are case sizes.

Is it possible to get the total weight for each row? If so, how would it be done?

e.g.

0.72kg  /* 12 x 0.060 = 0.72 */
1.92kg  /* 12 x 0.160 = 1.92 ... */
0.5kg
1kg
1kg
1.92kg
3kg

回答1:


Adding to the comment by @Tomalak, below is an example script you could use to populate the weight expression translation table.

CREATE TABLE dbo.Weights(
     Weight varchar(20) NOT NULL 
        CONSTRAINT PK_Weights PRIMARY KEY
    ,WeightInGrams int NULL
    ,WeightInKilograms AS CAST(WeightInGrams / 1000.0 AS decimal(10, 2))
);
GO

INSERT INTO dbo.Weights(Weight)
    SELECT DISTINCT Weight
    FROM dbo.Foo;
GO

DECLARE
      @Weight varchar(20)
    , @WeightInGrams int
    , @SqlExpression nvarchar(MAX);
DECLARE foo CURSOR LOCAL FAST_FORWARD FOR
    SELECT weight
    FROM dbo.Weights;
OPEN foo;
WHILE 1 = 1
BEGIN

    FETCH NEXT FROM foo INTO @Weight;

    IF @@FETCH_STATUS = -1 BREAK;
    
    BEGIN TRY

        SET @SqlExpression = 'SET @WeightInGrams = 
            ' + REPLACE(REPLACE(REPLACE(@Weight, 'x', '*'), 'kg', '000'), 'g', '');

        EXEC sp_executesql @SqlExpression
            , N'@WeightInGrams int OUTPUT'
            , @WeightInGrams = @WeightInGrams OUTPUT;

    END TRY
    BEGIN CATCH

        SET @WeightInGrams = NULL;

    END CATCH;

    UPDATE dbo.Weights
    SET WeightInGrams = @WeightInGrams
    WHERE Weight = @Weight;

END
CLOSE foo;
DEALLOCATE foo;
GO



回答2:


Function to calculate kg's in flow:

CREATE FUNCTION dbo.computeWeightKg(@weight NVARCHAR(50))
RETURNS NUMERIC
AS
BEGIN
    DECLARE @Result NUMERIC = 0; 
    DECLARE @Divider INT = 1;
    DECLARE @xIndex INT = NULL;

    IF (RIGHT(@weight, 2) = 'kg')
    BEGIN
        SET @weight = SUBSTRING(@weight, 1, LEN(@weight) - 2);
    END ELSE BEGIN
        SET @weight = SUBSTRING(@weight, 1, LEN(@weight) - 1);
        SET @Divider = 1000;
    END

    SET @xIndex = CHARINDEX('x', @weight)

    IF @xIndex = 0
    BEGIN
        SET @Result = CAST(@weight AS NUMERIC)
    END ELSE BEGIN
        DECLARE @x1 NVARCHAR = SUBSTRING(@weight, 1, @xIndex - 1);
        DECLARE @x2 NVARCHAR = SUBSTRING(@weight, @xIndex + 2, 50);

        SET @Result = CAST(@x1 AS NUMERIC) * CAST(@x2 AS NUMERIC);
    END

    RETURN @Result / @Divider;
END;



回答3:


I'm assuming the format of the column will be pretty similar to what you have given, so kg or g, and a single number or two numbers separated by an x, and maybe having spaces:

12 x 60g
12 x 160g
500g
1kg
12 x 250g

So we can create an inline function to do all this calculation with a series of APPLYs.:

CREATE FUNCTION GetCalculatedWeight
    (@val varchar(20))
RETURNS TABLE WITH SCHEMABINDING
AS RETURN
(
SELECT
    Result = v3.FirstNum * v3.SecondNum / v2.Factor

FROM
-- Remove spaces
    (SELECT Val = REPLACE(@val, ' ', '') ) v1
-- Get division factor and position of 'x'
OUTER APPLY (SELECT
    factor = CASE WHEN @val LIKE '%kg' THEN 1 ELSE 1000 END,
    toTakeOff = CASE WHEN @val LIKE '%kg' THEN 2 ELSE 1 END,
    x = CHARINDEX('x', v1.Val)
) v2

OUTER APPLY (SELECT
    FirstNum = TRY_CAST(
        CASE WHEN v2.x = 0 THEN
            LEFT(v1.Val, LEN(v1.Val) - v2.toTakeOff)
        ELSE
            LEFT(v1.Val, v2.x - 1)
        END
        AS int),
    SecondNum = CASE WHEN v2.x > 0 THEN
            TRY_CAST(SUBSTRING(v1.Val, v2.x + 1, LEN(v1.Val) - v2.toTakeOff - v2.x - 1) AS int)
        ELSE 1
        END
) v3

)

You use this by APPLYing it to your table:

SELECT t.*, Weight = wt.Result
FROM table t
CROSS APPLY dbo.GetCalculatedWeight (t.Weight) wt

If you have decimals then replace the TRY_CASTs to int with decimal.



来源:https://stackoverflow.com/questions/65577474/how-to-get-total-weight-of-a-case-size-e-g-12-x-160g-equal-to-1-92kg

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!