问题
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