在sql查询中使用函数

mko*_*mko 1 t-sql user-defined-functions

我构建了我的sql表,如下所示:

ItemID   Price   MaxPeople   CalculationUnit
1        10      4           people/item
2        70      2           item
3        30      8           week/item
4        50      2           week
Run Code Online (Sandbox Code Playgroud)

等等

现在我想运行一个类似的基本存储过程

sp_return_items_total
@Days as int,
@Items as int
AS
select itemid, price, total from table
Run Code Online (Sandbox Code Playgroud)

Total将是基于此计算的值(number of days * calculation unit * price).

例如,对于@Days = 5'@Items = 2',结果将是:

1, 10, 400  (10 * 4 people * 2 items * 5 days)
2, 70, 140 (70 * 1 * 2 items * 1)
3, 30, 42.85 (30 * 1 * 2 items * 5/7 days)
4, 50, 35.71 (50 * 1 * 1 items * 5/7 days)
Run Code Online (Sandbox Code Playgroud)

我试图找到一个解决方案,如何根据sp参数和计算单位获得总值.

感谢您的参与

HAB*_*ABO 5

编辑2/10/12:修改后的查询以对应修订的示例输出:

-- Set up the test data. 
declare @AmalgamatedStuff as table ( ItemId int, Price int, MaxPeople int, CalculationUnit varchar(16) ) 
insert into @AmalgamatedStuff ( ItemId, Price, MaxPeople, CalculationUnit ) values 
  ( 1, 10, 4, 'people/item' ), 
  ( 2, 70, 2, 'item' ), 
  ( 3, 30, 8, 'week/item' ), 
  ( 4, 50, 2, 'week' ) 

-- Stored procedure parameters. 
declare @Days as int = 5 
declare @Items as int = 2 

-- The query. 
select ItemId, Price, 
  case CalculationUnit 
    when 'item' then Price * @Items
    when 'people/item' then Price * MaxPeople * @Items * @Days 
    when 'week' then round( Price * @Days / 7.0, 2 )
    when 'week/item' then round( Price * @Items * @Days / 7.0, 2 )
    else NULL 
    end as Total 
  from @AmalgamatedStuff
Run Code Online (Sandbox Code Playgroud)

请注意,42.857142未能在第三行结果中舍入到42.85.


编辑:请记住,无法获得具有可变数量的列和未指定的计算的建议结果:

-- Set up the test data.
declare @AmalgamatedStuff as table ( ItemId int, Price int, MaxPeople int, CalculationUnit varchar(16) )
insert into @AmalgamatedStuff ( ItemId, Price, MaxPeople, CalculationUnit ) values
  ( 1, 10, 4, 'people/item' ),
  ( 2, 70, 2, 'item' ),
  ( 3, 30, 8, 'week/item' ),
  ( 4, 50, 2, 'week' )

-- Stored procedure parameters.
declare @Days as int = 5
declare @Items as int = 2

-- The query, give or take the correct calculations.
declare @SpuriousFactorToGetSuggestedResult as int = 2  
select ItemId, Price,
  case CalculationUnit
    when 'item' then Price * @Items
    when 'people/item' then Price * MaxPeople * @Items * @Days
    when 'week' then Price * @Items * @Days / 7
    when 'week/item' then Price * @Items * @Days * @SpuriousFactorToGetSuggestedResult / 7
    else NULL
    end as Total
  from @AmalgamatedStuff
Run Code Online (Sandbox Code Playgroud)

实际上,将查询存入过存储过程仍然是OP的练习.

"设计"仍然在腐臭之下,并且越来越快地溃烂.


编辑:回答以前编辑的"问题"仍然如下:

您可以使用CASE来执行以下操作:

select ItemId, Price,
  case
    when CalculationUnit = 'day' then @Days * Price
    when CalculationUnit = 'week' then @Days / 7 * Price
    else NULL
    end as 'Total'
  from MyIllConceivedTable
Run Code Online (Sandbox Code Playgroud)

如前所述,这是一个糟糕的设计.

在某些情况下,拥有一个查找表可能是有意义的,例如,可以让您将各种度量单位映射到某个公共基础.考虑权重和它们的克当量.(也是存储全名"Ounces"和缩写"Oz"的便利位置,......)您的数据表将包含对单位表的引用.

在某些情况下,它可能与时间单位有关.预定事件可能每天,每周,每月,每季度和每年重复发生.单元的长度有些灵活,用途往往很奇特.(我在每个月的第3个星期三吃午饭.见到你了吗?)

关于性能,返回结果的计算也不错.您可以使用计算列或视图来实现(恶意)结束.当您为每一行调用函数时,性能会受到影响,例如,将DATETIME列转换为字符串的WHERE子句使用LIKE来确定字符串中是否存在"R".

无论你选择什么,请不要使用像daffy那样的东西:

declare @Today as Date
set @Today = SysDateTime()
select @Today,
  DateDiff(day, @Today, DateAdd( "day", 1, @Today ) ) as 'Days in a Day',
  DateDiff(day, @Today, DateAdd( "week", 1, @Today ) ) as 'Days in a Week',
  DateDiff(day, @Today, DateAdd( "month", 1, @Today ) ) as 'Days in a Month' -- Sometimes!
Run Code Online (Sandbox Code Playgroud)