我正在尝试重新编写基于游标的查询。
查询根据多个值计算某些统计信息。在下面的代码段中,第一个,第二个和第三个CASE
解决了Unit1
的幸福。这些字段中的任何一个都是0(它们永远不会是NULL
)我会收到Divide by Zero
错误。我可以在每个字段(Unit2 + 1) / (Unit1 + 1)
中添加1,这将停止错误。但是,它似乎是一个躲避,它可能会给出不正确的结果。即。 Unit1
需要相同数量的Unit2
才能让他们满意。如果我有一个Unit1
而没有Unit2
,那么这个支票会给予100%的支持。所以我的第一个问题是如何防止除以零而不是扭曲结果。每个CASE
都会给我一个%
快乐
Select
CASE WHEN ((Unit2 / Unit1) * 100) > 100 Then 100 Else ((Unit2 / Unit1) * 100) END Unit1Happy1,
CASE WHEN ((Stock3 / (Unit1 * 2)) * 100) > 100 Then 100 Else ((Stock3 / (Unit1 * 2)) * 100) END Unit1Happy2,
CASE WHEN (((Drug3 + (Drug1 / 2)) / Unit1) * 100) > 100 Then 100 Else (((Drug3 + (Drug1 / 2)) / Unit1) * 100) END Unit1Happy3,
CASE WHEN (((Weapon6 + Weapon7 + Weapon8 + Weapon9) / Unit2) * 100) > 100 Then 100 ELSE (((Weapon6 + Weapon7 + Weapon8 + Weapon9) / Unit2) * 100) END Unit2Happ1,
CASE WHEN (((Stock2 + (Stock1 / 2)) / Unit2) * 100) > 100 Then 100 Else (((Stock2 + (Stock1 / 2)) / Unit2) * 100) END Unit2Happ2
FROM tblUserFiles
我的下一个问题是我需要为每个UnitHappiness取最低值并将该值存储在表中。因此,在tblUserFiles
中有5个字段Unit1Happ
,Unit2Happ
.... Unit5Happ
。查看上面的查询,如果Unit1Happy1
是最低的数字,我将该数字存储到Unit1Happ
,如果Unit2Happy
是我存储的最低等等。
我的记录标识符为UserId
,我需要为给定的UserId
或整个表运行此记录。
我基本上要问的是:
更新
我正在处理以下答案中发布的建议。由于这只是一次训练,可能需要一段时间。我有一个工作查询,提供我正在寻找的结果我只是不确定建议的答案是否会更有效。
Update tblUserFiles Set Unit1Happ = happyvals.Unit1Happiness, Unit2Happ = happyvals.Unit2Happiness, Unit3Happ = happyvals.Unit3Happiness, Unit4Happ = happyvals.Unit4Happiness, Unit5Happ = happyvals.Unit5Happiness FROM
(SELECT ch.UserId,
Case When ch.Unit1Happy1 < ch.Unit1Happy2 And ch.Unit1Happy1 < ch.Unit1Happy3 Then ch.Unit1Happy1
When ch.Unit1Happy2 < ch.Unit1Happy1 And ch.Unit1Happy2 < ch.Unit1Happy3 Then ch.Unit1Happy2
Else ch.Unit1Happy3
End As Unit1Happiness,
CASE WHEN ch.Unit2Happy1 > ch.Unit2Happy2 THEN ch.Unit2Happy1
ELSE ch.Unit2Happy2
END AS Unit2Happiness,
ch.Unit3Happy1 AS Unit3Happiness,
ch.Unit4Happy1 AS Unit4Happiness,
ch.Unit5Happy1 AS Unit5Happiness
FROM
(
Select
UserId,
CASE WHEN Unit2 = 0 OR Unit1 = 0 THEN 0
WHEN ((Unit2 / Unit1) * 100) > 100 Then 100
ELSE ((Unit2 / Unit1) * 100)
END Unit1Happy1,
CASE WHEN Stock3 = 0 OR Unit1 = 0 THEN 0
WHEN ((Stock3 / (Unit1 * 2)) * 100) > 100 THEN 100
ELSE ((Stock3 / (Unit1 * 2)) * 100)
END Unit1Happy2,
CASE WHEN Unit1 = 0 THEN 0
WHEN Drug3 = 0 AND Drug1 = 0 THEN 0
WHEN Drug1 = 0 THEN
CASE WHEN (Drug3 / Unit1) * 100 > 100 THEN 100
ELSE (Drug3 / Unit1) * 100
END
WHEN Drug3 = 0 THEN
CASE WHEN (Drug1 / 2) / Unit1 > 100 THEN 100
ELSE (Drug1 / 2) / Unit1
END
ELSE
CASE WHEN (((Drug3 + (Drug1 / 2)) / Unit1) * 100) > 100 THEN 100
ELSE (((Drug3 + (Drug1 / 2)) / Unit1) * 100)
END
END Unit1Happy3,
CASE WHEN Unit2 = 0 THEN 0
WHEN (Weapon6 + Weapon7 + Weapon8 + Weapon9) = 0 THEN 0
WHEN (((Weapon6 + Weapon7 + Weapon8 + Weapon9) / Unit2) * 100) > 100 THEN 100
ELSE (((Weapon6 + Weapon7 + Weapon8 + Weapon9) / Unit2) * 100)
END Unit2Happy1,
CASE WHEN Unit2 = 0 THEN 0
WHEN Stock1 = 0 AND Stock2 = 0 THEN 0
WHEN Stock1 = 0 THEN
CASE WHEN ((Stock2 / Unit2) * 100) > 100 THEN 100
ELSE ((Stock2 / Unit2) * 100)
END
WHEN Stock2 = 0 THEN
CASE WHEN (((Stock1 / 2) / Unit2) * 100) > 100 THEN 100
ELSE (((Stock1 / 2) / Unit2) * 100)
END
WHEN (((Stock2 + (Stock1 / 2)) / Unit2) * 100) > 100 THEN 100
ELSE (((Stock2 + (Stock1 / 2)) / Unit2) * 100)
END Unit2Happy2,
CASE WHEN Unit2 = 0 OR Unit3 = 0 THEN 0
WHEN ((Unit2 / Unit3) * 100) > 100 THEN 100
ELSE ((Unit2 / Unit3) * 100)
END Unit3Happy1,
CASE WHEN Unit2 = 0 OR Unit4 = 0 THEN 0
WHEN ((Unit2 / Unit4) * 100) > 100 THEN 100
ELSE ((Unit2 / Unit4) * 100)
END Unit4Happy1,
CASE WHEN Unit2 = 0 OR Unit5 = 0 THEN 0
WHEN ((Unit2 / Unit5) * 100) > 100 THEN 100
ELSE ((Unit2 / Unit5) * 100)
END Unit5Happy1
FROM tblUserFiles) ch) happyvals
Join tblUserFiles ON tblUserFiles.UserID = happyvals.UserID
答案 0 :(得分:0)
在每个分组周围放一个nullif(Unit1, 0)
?
答案 1 :(得分:0)
像这样。
我们的想法是将您的部门包装在UDF(标量用户定义函数)中....并使用“Max(v)”技巧。
下面的代码可能不完美,我提供了这个想法。
游标是可怕的表现者,99.9%的时间。尝试在没有游标的情况下解决这个问题。
/* or Create */
ALTER FUNCTION dbo.udfSafeDivision (@num float , @denom float)
RETURNS float
AS
BEGIN
declare @returnValue float
select @returnValue = 0
if(isnull(@denom,0) != 0)
BEGIN
select @returnValue = convert(float, convert(float, @num)/convert(float, @denom))
END
return @returnValue
END
GO
IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL
begin
drop table #TableOne
end
CREATE TABLE #TableOne
(
SurrogateKey int IDENTITY(1001, 1),
Unit1 int ,
Unit2 int ,
Stock1 int ,
Stock2 int ,
Stock3 int ,
Drug1 int ,
Drug3 int ,
Weapon6 int , Weapon7 int , Weapon8 int , Weapon9 int
)
Insert into #TableOne (Unit1, Unit2, Stock1, Stock2 , Stock3 , Drug1, Drug3 , Weapon6 , Weapon7 , Weapon8 , Weapon9)
select 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 0 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 6 , 0 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 6 , 7 , 0 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 0 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 0
UNION ALL select 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11
UNION ALL select 5 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 5 , 0 , 0 , 0 , 5 , 0 , 0 , 0 , 0 , 0 , 0
UNION ALL select 10 , 0 , 0 , 0 , 0 , 5 , 10 , 0 , 0 , 0 , 0
UNION ALL select 0 , 1 , 0 , 0 , 0 , 5 , 10 , 10 , 20 , 30 , 40
UNION ALL select 0 , 50 , 20 , 10 , 0 , 0 , 0 , 0 , 0 , 0 , 0
SELECT
(SELECT Max(v)
FROM (VALUES (Unit1Happy1), (Unit1Happy2), (Unit1Happy3), (Unit2Happ1), (Unit2Happ2)) AS value(v)) as [MaxValue]
, '--------' as Sep1
, derived1.*
FROM
(
Select
CASE WHEN ((dbo.udfSafeDivision(Unit2 , Unit1)) * 100) > 100 Then 100 Else (dbo.udfSafeDivision(Unit2 , Unit1) * 100) END Unit1Happy1,
CASE WHEN (dbo.udfSafeDivision(Stock3 , (Unit1 * 2)) * 100) > 100 Then 100 Else (dbo.udfSafeDivision(Stock3 , (Unit1 * 2)) * 100) END Unit1Happy2,
CASE WHEN (dbo.udfSafeDivision((Drug3 + (Drug1 / 2)) , Unit1) * 100) > 100 Then 100 Else (dbo.udfSafeDivision((Drug3 + (Drug1 / 2)) , Unit1) * 100) END Unit1Happy3,
CASE WHEN (dbo.udfSafeDivision((Weapon6 + Weapon7 + Weapon8 + Weapon9) , Unit2) * 100) > 100 Then 100 ELSE (dbo.udfSafeDivision((Weapon6 + Weapon7 + Weapon8 + Weapon9) , Unit2) * 100) END Unit2Happ1,
CASE WHEN (dbo.udfSafeDivision((Stock2 + (Stock1 / 2)) , Unit2) * 100) > 100 Then 100 Else (dbo.udfSafeDivision((Stock2 + (Stock1 / 2)) , Unit2) * 100) END Unit2Happ2
/* the below is to debug */
, '--' as Sep1
, Unit1, Unit2, Stock1, Stock2 , Stock3 , Drug1, Drug3 , Weapon6 , Weapon7 , Weapon8 , Weapon9
, dbo.udfSafeDivision(Unit2 , Unit1) as Div1
, dbo.udfSafeDivision(Stock3 , (Unit1 * 2)) as Div3
FROM #TableOne
) as derived1
IF OBJECT_ID('tempdb..#TableOne') IS NOT NULL
begin
drop table #TableOne
end