2012-01-22 54 views
1

我我的結構SQL表是這樣的:使用功能

ItemID Price MaxPeople CalculationUnit 
1  10  4   people/item 
2  70  2   item 
3  30  8   week/item 
4  50  2   week 

現在我想運行一個基本的存儲過程,看起來像

sp_return_items_total 
@Days as int, 
@Items as int 
AS 
select itemid, price, total from table 

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) 

我試圖找到一個解決方案,如何讓基於對SP的參數和計算單元的總價值。

感謝您的參與

+0

面臨的挑戰之一,以書面形式產生期望結果的查詢是前兩個結果行有三列wihle最後兩個結果行有四個。大多數查詢爲每一行返回相同數量的列。 – HABO

+0

@ user92546看起來像沒有尾隨空格的逗號是小數點分隔符(檢查計算)... –

回答

5

EDIT 12年2月10日:修訂的查詢,以對應於修改後的輸出樣本:

-- 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」的方便之處,...)。您的數據表將包含對單位表的引用。

在某些情況下,它可能對時間單位有意義。計劃的事件可能每天,每週,每月,每季度和每年發生。單位的長度有些靈活,用途往往是奇特的。 (我每個月的第3個週三吃午飯,在那裏見?)

關於性能,返回結果的計算結果並不差。您可以使用計算列或視圖來實現您的(惡意)結束。當您爲每行調用函數時,性能會受到影響,例如一個將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! 
4

是的。替代方案(以及良好的數據庫設計)是將計算單元存儲爲某個單元的係數。換句話說,如果選項是白天和星期,則存儲天數(意思是對於當前說day7的任何行,當前說week的任何行,您將存儲1),以便您可以在您的計算。

1

使用具有數據訪問「隱藏」在其內部存儲的功能,是的,這可以大幅減少你的表現(主要是因爲它們可能會被執行的事實,更往往超出你的想象,一見鍾情) 。

主要做計算的功能(如它可能會在這裏)不應該是一個主要問題。