我有这个用户函数,它总是被标记为非确定性的,尽管只要输入参数相同,该值将始终相同。我读过的所有内容都表明这应该是确定性的。
有人可以找到原因吗?
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[udfGetCriteriaScore]
(
@InputString varchar(max)
)
RETURNS int
WITH SCHEMABINDING
AS
BEGIN
DECLARE @returnScore int;
DECLARE @IdentifierChar NCHAR(1)= '"'
DECLARE @overallScore int
DECLARE @FirstID int
DECLARE @SecondID int
DECLARE @TargetString varchar(MAX)
DECLARE @startDateCriteria varchar(MAX);
DECLARE @endDateCriteria varchar(MAX);
declare @scoringTable table (
Criterion varchar(max),
CriteriaScore int,
Occurances int,
SumTotalScore int
)
DECLARE @TotalCriterions int = (SELECT LEN(@InputString) - LEN(REPLACE(@InputString, '@', '')))
declare @COUNT int = 0
declare @Length int = 0
WHILE(@COUNT) < @TotalCriterions
BEGIN
Set @FirstID = CHARINDEX(@IdentifierChar, @InputString, @Length)
Set @SecondID = CHARINDEX(@IdentifierChar, @InputString, @FirstID + 1)
Set @Length = @SecondID - @FirstID
Set @TargetString = SUBSTRING(@InputString, @FirstID + 1, @Length - 1)
SET @COUNT = @COUNT + 1
Set @Length = @SecondID + 1
DECLARE @criteriaScore int
DECLARE @criteriaCount int
DECLARE @Criterion varchar(max)
SET @Criterion = SUBSTRING(@TargetString, 0, CHARINDEX(':', @TargetString))
-- Calculate date range score
IF (LOWER(@Criterion) = '@fromdate' OR LOWER(@Criterion) = '@todate')
BEGIN
IF LOWER(@Criterion) = '@fromdate'
SET @startDateCriteria = SUBSTRING(@TargetString, CHARINDEX(':', @TargetString) + 2, LEN(@TargetString) - CHARINDEX(':', @TargetString))
IF LOWER(@Criterion) = '@todate'
SET @endDateCriteria = SUBSTRING(@TargetString, CHARINDEX(':', @TargetString) + 2, LEN(@TargetString) - CHARINDEX(':', @TargetString))
IF @startDateCriteria IS NOT NULL AND @endDateCriteria IS NOT NULL
BEGIN
SET @criteriaScore = 5
SET @criteriaCount = DATEDIFF (dd, @startDateCriteria, @endDateCriteria)
INSERT INTO @scoringTable
(Criterion, CriteriaScore, Occurances, SumTotalScore)
VALUES
('DateRange', @criteriaScore, @criteriaCount, (@criteriaScore * @criteriaCount))
END
END
ELSE
-- Calculate individual criterion score
BEGIN
SET @criteriaScore =
CASE
WHEN LOWER(@Criterion) = '@branchid' THEN 10
WHEN LOWER(@Criterion) = '@locationid' THEN 10
WHEN LOWER(@Criterion) = '@salesexecid' THEN 1
WHEN LOWER(@Criterion) = '@thedate' THEN 5
ELSE 1
END
SET @criteriaCount =
(SELECT
CASE
WHEN LEN(REPLACE(@TargetString, @Criterion, '')) < 3 THEN 0
ELSE LEN(@TargetString) - LEN(REPLACE(@TargetString, ';', '')) + 1
END
)
INSERT INTO @scoringTable
(Criterion, CriteriaScore, Occurances, SumTotalScore)
VALUES
(@Criterion, @criteriaScore, @criteriaCount, (@criteriaScore * @criteriaCount))
END
END
IF EXISTS (SELECT Occurances from @scoringTable where Occurances > 0 AND LOWER(Criterion) in ('@salesexecid', '@locationid'))
UPDATE @scoringTable SET SumTotalScore = 0 where LOWER(Criterion) = '@branchid'
set @returnScore = (select SUM(SumTotalScore) from @scoringTable)
Return @returnScore;
END
它旨在分割出这样的字符串:
["@BranchID: 154","@FromDate: 2018-02-01T00:00:00","@ToDate: 2018-02-26T00:00:00","@SalesExecID: "]
并根据日期范围,包括的分支数等返回总分。
以下IsDeminministic检查始终为0?
SELECT OBJECTPROPERTY(OBJECT_ID('[dbo].[udfGetCriteriaScore]'), 'IsDeterministic')
答案 0 :(得分:2)
其他人也遇到同样的问题:
https://www.sqlservercentral.com/Forums/Topic1545616-392-1.aspx
在那里,解决方案是将字符串日期转换为实际日期:
您需要使用显式CONVERT来使用字符串文字。一世 稍微更改了您的代码以删除+1
#Normalize data
data[,1:(ncol(data)-1)] = normalize(data[,1:(ncol(data)-1)])
data[,ncol(data)] = as.numeric(data[,ncol(data)]) - 1
set.seed(128)
ind = sample(2,nrow(data),replace = T,prob = c(0.7,0.3))
training = data[ind==1,1:(ncol(data)-1)]
test = data[ind==2,1:(ncol(data)-1)]
traintarget = data[ind==1,ncol(data)]
testtarget = data[ind==2,ncol(data)]
# One hot encoding
trainLabels = to_categorical(traintarget)
testLabels = to_categorical(testtarget)
print(testLabels)
model = keras_model_sequential()
model %>%
layer_dense(units = 150, activation = 'relu', input_shape = c(520)) %>%
layer_dense(units = 50, activation = 'relu') %>%
layer_dense(units = 9, activation = 'softmax')
model %>%
compile(loss = 'categorical_crossentropy', optimizer = 'adam',metrics = 'accuracy')
history = model %>%
fit(training,
trainLabels,
epoch = 300,
batch_size = 32,
validation_split = 0.2)
prob = model %>%
predict_proba(test)
pred = model %>%
predict_classes(test)
table2 = table(Predicted = pred, Actual = testtarget)
cbind(prob,pred,testtarget)
同样的答案解释了这是因为日期格式是非确定性的,因此您需要明确设置字符串转换的(确定性)日期格式才能被视为确定性。