我有一张表,本质上是一个客户清单,包含许多'bit'和'datetime'字段。对于位字段,1表示已完成,0表示未完成,日期时间字段包含有关特定核对表项目何时完成的信息。每个核对表项目实际上都是一个单独的列。我知道这可能不是最干净的设计,但它是我提出的最好的。
现在,我正在尝试编写一个标量值函数,通过核对表评估客户端的进度。此函数循环遍历位类型的所有列,并查看有多少是1或0,并返回完成百分比。
请参阅以下代码
ALTER FUNCTION [dbo].[Get_ClientProgress]
(
-- ClientID parameter refers to ClientID column in CHECKLIST Table
@ClientID int
)
RETURNS float
AS
BEGIN
DECLARE
@totalRows int,
@fieldChecked bit,
@colBuffer nvarchar(50),
@intCounter int,
@valueBuffer int, -- holds the cumulative total of bit fields that are marked true in CHECKLIST Table
@sql nvarchar(max),
@ClientProgress float
-- temporary table to hold column names
DECLARE @temp TABLE
(
Row int,
Column_Name nvarchar(50)
)
-- First, get the total number of 'bit' fields in the CHECKLIST table
SELECT @totalRows = Count(Data_type)
FROM information_schema.columns
WHERE data_type = 'bit' AND Table_Name = 'CHECKLIST'
-- the purpose of @temp is just to reorganize the CHECKLIST table in a top to bottom fashion instead of left to right
-- This makes it easier to loop through each field
INSERT INTO @temp
SELECT row_number() OVER(ORDER BY Column_name) as Row, Column_name
FROM information_schema.columns
WHERE data_type = 'bit' AND Table_Name = 'CHECKLIST'
SET @intcounter= 1 -- counter used for the loop; will also hold row number
SET @valueBuffer = 0 -- will hold the cumulative value
-- begin loop to find how many fields are marked true
WHILE (@intCounter <= @totalRows)
BEGIN
SET @colBuffer = (SELECT Column_Name FROM @temp WHERE Row = @intCounter)
-- The next line is where I'm having trouble
SET @fieldChecked = (SELECT (CASE WHEN @colBuffer = 1 THEN 1 ELSE 0 END) FROM [dbo].[CHECKLIST] WHERE ClientID = @ClientID)
SET @valueBuffer = @valueBuffer + @fieldChecked
SET @intCounter = @intCounter + 1
END
IF @valueBuffer is NULL
SELECT @ClientProgress = 0
ELSE
SELECT @ClientProgress = CAST(@valueBuffer as float) / CAST(@totalRows as float)
-- Return the result of the function
RETURN @ClientProgress
END
在上面的代码中,我无法使用给定的SELECT语句为@fieldChecked赋值。我只是想获取@colBuffer中保存的特定列名的位值。我也尝试过以下陈述,但这些都没有奏效:
SELECT @colBuffer FROM BUYER_CHECKLIST WHERE ClientID = @ClientID
SELECT TOP 1 @colBuffer FROM BUYER_CHECKLIST WHERE ClientID = @ClientID
SELECT COUNT(CASE WHEN @colBuffer = 1 THEN 1 ELSE 0 END) FROM BUYER_CHECKLIST WHERE ClientID = @ClientID
SELECT SUM(CASE WHEN @colBuffer = 1 THEN 1 ELSE 0 END) FROM BUYER_CHECKLIST WHERE ClientID = @ClientID
我在这里做错了什么?
答案 0 :(得分:0)
试试这个:(你似乎有太多的括号): 改变:
SET @fieldChecked = (SELECT (CASE WHEN @colBuffer = 1 THEN 1 ELSE 0 END)
为:
SELECT @fieldChecked= CASE WHEN @colBuffer = 1 THEN 1 ELSE 0 END tempname FROM
答案 1 :(得分:0)
看起来你只是在@colBuffer中选择了值,而不是在该值之后命名的列中的任何内容。您需要创建动态sql。这是一个例子:
create table #sample (
ID int,
colA nvarchar(100),
colB nvarchar(100)
)
insert #sample values
(1, 'xxx', 'yyy')
declare @colBuffer nvarchar(100) = 'colA'
-- ONE WAY:
declare @sql nvarchar(max) = '
select ' + @colBuffer + ' from #sample
'
exec(@sql)
-- ANOTHER WAY:
select case
when @colBuffer = 'colA' then colA
when @colBuffer = 'colB' then colB
else ''
end
from #sample
drop table #sample