编辑 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
请注意,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
实际上将查询放入存储过程中作为 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
如前所述,这是一个糟糕的设计。
在某些情况下,使用查找表可能很有意义,例如可以让您将各种度量单位映射到某个公共基础的东西。想想重量和它们的克当量。 (也是存储全名“Ounces”和缩写“Oz”,...的便利位置。)您的数据表将包含对单位表的引用。
在某些情况下,它可能对时间单位有意义。预定事件可能每天、每周、每月、每季度和每年重复发生。单元的长度有些灵活,用途往往很特殊。 (我每个月的第三个星期三吃午饭。在那里见?)
关于性能,返回结果的计算还不错。您可以使用计算列或视图来实现您的(邪恶的)目的。当您为每一行调用函数时,性能会受到影响,例如将 DATETIME 列转换为字符串并使用 LIKE 来确定字符串中是否存在“R”的 WHERE 子句。
无论你选择什么,请不要使用任何愚蠢的东西:
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!