任何C#/ T-SQL专家都可以帮助我吗?我很难将这个C#代码转换为T-SQL。
这是C#代码:
public (int distance, int absoluteDistance) MinimumDayOfWeekDistance(DayOfWeek dayOfWeekOne,
DayOfWeek dayOfWeekTwo)
{
int forwardDaysDifference(int iteratorDayOfWeekOne, int iteratorDayOfWeekTwo) => iteratorDayOfWeekTwo -
iteratorDayOfWeekOne +
((iteratorDayOfWeekOne >
iteratorDayOfWeekTwo)
? 7
: 0);
int forwardOneTwo = forwardDaysDifference((int) dayOfWeekOne, (int) dayOfWeekTwo);
int forwardTwoOne = forwardDaysDifference((int) dayOfWeekTwo, (int) dayOfWeekOne);
if (forwardOneTwo < forwardTwoOne)
{
return (forwardOneTwo, forwardOneTwo);
}
return (-forwardTwoOne, forwardTwoOne);
}
public int DaysToClosestDayOfWeek(DayOfWeek dayOfWeekOne, List<DayOfWeek> dayOfWeekList)
{
return dayOfWeekList.Select(dayOfWeek => MinimumDayOfWeekDistance(dayOfWeekOne, dayOfWeek))
.Aggregate((x, y) => (x.absoluteDistance < y.absoluteDistance)
? x
: ((x.absoluteDistance == y.absoluteDistance) ? ((x.distance > 0) ? x : y) : y)).distance;
}
以下是实施:
int dayOfWeekDistance = this.DaysToClosestDayOfWeek(passedInDateParameter.DayOfWeek, myDayOfWeekList);
passedInDateParameter = passedInDateParameter.AddDays(dayOfWeekDistance);
这个想法是你有一个列表(C#侧的DayOfWeekList),并且该列表可以在一周中的任何一天填充。可能是周一和周二,可能是周二,周三,周五和周六等。
传入的DateTime参数与该列表进行比较,并根据列表中最接近的工作日进行更新。
例如,如果传入的DateTime参数是星期日,而我的DayOfWeek列表包含星期三和星期六,则该参数需要移回星期六,因为它在列表中最接近。
同样,如果我的列表包含星期日,星期一和星期六,并且传入的参数是星期四,则该参数必须移至星期六。
最后,如果参数与列表中的两个工作日相等(周三传入,周一和周五在列表中......或周日传入,周二和周五在列表中),则参数需要向前移动到下一个最接近的工作日(在第一种情况下,将是星期五,在第二种情况下是星期二)。
到目前为止,在SQL方面,我有一个VARCHAR变量,表示基于每个工作日的数字列表。例如,变量类似于&#34; 126&#34;如果星期日,星期一和星期五应该包含在变量中。
此外,在SQL方面,最好从列表中最接近的工作日返回输入参数的最小距离。
例如,如果我在星期四(或当前实施的方式为5)以及星期日,星期一和星期二传入列表(或1,2和3),则应该-2返回(因为星期二在列表中最接近星期四),这样我就可以从目标日期时间变量中减去2天(日期时间变量超出了这个问题的范围,仅供参考)。
简单地说,应该返回输入参数距离最接近的星期几的距离,它们可以是正数或负数,以便有效地计算应该添加或减去的天数。
到目前为止,实现在C#中运行良好,我只是很难将其转换为SQL,因为它不是我最好的语言。
对此的任何帮助将不胜感激。
答案 0 :(得分:0)
我已经找到了答案。首先,SQL Fiddle
这是SQL:
create table test_Table (Days int);
declare @DaysList int
declare @x int
declare @Day int
set @DaysList = 36
/*This is the variable that you mention in your original question.
For example, 36 means Tuesday and Friday*/
set @Day = 1
/*This is the day that you're checking against*/
set @x = 1
/*This is just our while loop variable*/
WHILE @x <= len(@DaysList)
BEGIN
INSERT INTO test_Table
SELECT substring(cast(@DaysList as nvarchar(7)),@x,1)
SET @X = @X + 1
END
/*The while loop is taking each digit in your @DaysList variable
and putting it in its own row.
This makes it so that we can compare our day to each day in the list
more easily.*/
;with cte as (SELECT case when abs(@Day-days) < 7-abs(@Day-days)
then abs(@Day-days)
else 7-abs(@Day-days) end daysDiff
/*This field finds the number of days between the @Day value and the day
from @DaysList that we're comparing to. Basically, the smaller the number
the better.*/
, days
/*This value is going to be the result of our query*/
, case when days-@Day between 0 and 8
then days-@Day
when days+7-@day between 0 and 8
then days+7-@Day
else -100 end a
/*This is doing a bunch of stuff to meet the requirement of finding the "next day"
if the day is in the next week (for example, if @DaysList is Friday and Sunday (6 and 1)
and our @Day is Saturday (7), we want to show 1, not 6.*/
FROM #test_Table)
SELECT TOP 1 days FROM cte ORDER BY DaysDiff Asc, a
/*this just gives us our final result.*/
如果您希望将其作为SQL函数,则可以创建函数:
create function ClosestDayToDate(@Day int, @DaysList int)
RETURNS int AS BEGIN
declare @x int
declare @result int
declare @test_table table (days int)
set @x = 1
WHILE @x <= len(@DaysList)
BEGIN
INSERT INTO @test_Table
SELECT substring(cast(@DaysList as nvarchar(7)),@x,1)
SET @X = @X + 1
END
;with cte as (SELECT case when abs(@Day-days) < 7-abs(@Day-days)
then abs(@Day-days)
else 7-abs(@Day-days) end daysDiff
, days
, case when days-@Day between 0 and 8
then days-@Day
when days+7-@day between 0 and 8
then days+7-@Day
else -100 end a
FROM @test_Table)
Select @Result = (SELECT TOP 1 days FROM cte ORDER BY DaysDiff Asc, a)
return @result
END
然后,您可以运行该功能:
SELECT dbo.ClosestDayToDate(1,72)
哪会返回2
。
如果您需要更多澄清,请告诉我。
编辑:我仍然非常喜欢这个功能,所以我继续编辑它以缩短它。我认为这是我能得到的最短时间而不是完全重新编写它的编写方式,但是:create function ClosestDayToDate(@Day int, @DaysList int)
RETURNS int AS BEGIN
declare @x int
declare @result int
declare @test_table table (days int)
set @x = 1
WHILE @x <= len(@DaysList)
BEGIN
INSERT INTO @test_Table
SELECT substring(cast(@DaysList as nvarchar(7)),@x,1)
SET @X = @X + 1
END
;with cte as (SELECT days
, case when days-@Day between 0 and 8
then days-@Day
when days+7-@day between 0 and 8
then days+7-@Day
end a
FROM @test_Table)
Select @Result = (SELECT TOP 1 days FROM cte ORDER BY a)
return @result
END
这是函数的SQL Fiddle。
编辑:根据您的要求,我已更新了该功能。现在它将显示投放的“日期”和“日期列表”中最近的日期之间的天数。如果日期在之前,它将显示负数。
仅供参考 - 我没有像以前的版本那样对此进行详尽的测试,但在我做过的测试中,它工作正常。
create function ClosestDayToDate(@Day int, @DaysList int)
RETURNS int AS BEGIN
declare @x int
declare @result int
declare @test_table table (days int)
set @x = 1
WHILE @x <= len(@DaysList)
BEGIN
INSERT INTO @test_Table
SELECT substring(cast(@DaysList as nvarchar(7)),@x,1)
SET @X = @X + 1
END
;with cte as (SELECT days
, case when abs(days-@Day) < days+7-@Day then days-@Day else days+7-@Day end b
, case when abs(days-@Day) < days+7-@Day then abs(days-@Day) else days+7-@Day end c
FROM @test_Table)
Select @Result = (SELECT TOP 1 b FROM cte ORDER BY c, b desc)
return @result
END