sql 求模 实现 贪婪算法

背景:

最近在维护一个项目, 因新功能需求拓展.  有一个字段存储 一个星期中的几天,可能是全部,也有可能只是其中的星期一, 星期三,等.

因为项目中有一个枚举值, 已作好初始化赋值工作, 而且 客户端开发时直接把组合值合并成一个早已存入这个字段到DB.

我在项目别的地方(动态批量生成月报表时,又需要得到这个具体的频率值. 因为每个月有几个星期一,星期三,不是固定的, 需要动态计算.),  所以, 又需要将其还原为 其中具体对应的 星期一,星期三 等. 这里就需要对这个组合值,进行求模操作. 于是便有了本文.

运行环境: sql server 2014

测试环境: sql server 2005

求模结果:   请见 ActualMapping 列对应的值

eg1: 1025 = 1024 * 1 + 1

eg2:  1552 = 1024 * 1 + 512 * 1 + 16 * 1

我们数据库中,有条记录,某个字段值存的就是1552, 表示频率取 每周五,每周六,每周日各一次

sql脚本:

declare @total bigint

set @total=1552
--55451121212121
--784546
--2558=1024*2 + 256*1 + 128 * 1 + 64 * 1 + 32 * 1 + 16 * 1 + 1 * 14
--1552= 1024*1 + 512 * 1 + 16*1
--1553= 1024*1 + 512 * 1 + 16*1 + 1 * 1
-- 1554 = 1024*1 + 512 * 1 + 16*1 + 1 * 2
-- 1025 = 1024* 1 + 1 * 1

declare @tblRecurrenceType table
(
 [DayName] varchar(20),
 [DayValue] bigint,
 [ActualMapping] bigint default (0),
 ID bigint identity
)

insert into @tblRecurrenceType
(
	 [DayName],
	 [DayValue]
)
select 'EverySaturday',1024
--union all select 'EveryWorkday',992
union all select 'EveryFriday',512
union all select 'EveryThursday',256
union all select 'EveryWednesday',128
union all select 'EveryTuesday',64
union all select 'EveryMonday',32
union all select 'EverySunday',16
union all select 'UNknown',1

--select  * from @tblRecurrenceType

declare @iTime bigint
	set @iTime=0;
declare @tmpDayValue bigint
	set @tmpDayValue=0
declare @tmpActualMapping bigint
	set @tmpActualMapping=0

declare @iTblRowCount bigint
	SET @iTblRowCount=0
 SELECT @iTblRowCount=count(*) from @tblRecurrenceType

while @total>0
begin
	 set @[email protected]+1;

	 select @tmpDayValue=DayValue from @tblRecurrenceType where [email protected]

      if(@total<@tmpDayValue)
      begin
            if(@[email protected])
            begin
				update @tblRecurrenceType set [email protected]
				from @tblRecurrenceType where [DayValue]<[email protected]
            end
            else
            begin
				update @tblRecurrenceType set ActualMapping=1
				from @tblRecurrenceType where [DayValue][email protected]
            end

            continue
      end
      else
      begin
		  set @[email protected] / @tmpDayValue
		  if(@tmpActualMapping>0)
		  begin
				update @tblRecurrenceType set [email protected]
				from @tblRecurrenceType where [DayValue][email protected]

				set @total = @total % @tmpDayValue
		  end
		  else
		  begin
			   update @tblRecurrenceType set ActualMapping=1
			   from @tblRecurrenceType where [DayValue][email protected]

			  set @total = @total - @tmpDayValue 

			  if(@total<0)
				 break
		  end
     end

end

--select @iTime  -- running times
select * from @tblRecurrenceType  -- get those ActualMapping
select * from @tblRecurrenceType  where ActualMapping>0 -- get those ActualMapping

备注:

本来,可以写得相对简单一些. 但完成我需要的功能后. 发现这其实就是一个贪婪算法的实现. 想起了N久前某位老师提到的售票员找零问题, 于是, 便有了上面的sql脚本.

在上面的初始化值中 特意加了一行 UNknown , 单位为1, 确保求模结果完全正确.

( 结束)

时间: 2024-10-25 08:46:55

sql 求模 实现 贪婪算法的相关文章

nyoj 次方求模

次方求模 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 求a的b次方对c取余的值 输入 第一行输入一个整数n表示测试数据的组数(n<100) 每组测试只有一行,其中有三个正整数a,b,c(1=<a,b,c<=1000000000) 输出 输出a的b次方对c取余之后的结果 样例输入 3 2 3 5 3 100 10 11 12345 12345 样例输出 3 1 10481 #include<cstdio> #include<cstdlib

杭电ACM 二 数学求模

Font Size: ← → Problem Description A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. Given A, B, and n, you are to calculate the value of f(n). Input The input consists of multiple test cases. Ea

NYOJ 102 次方求模

次方求模 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 求a的b次方对c取余的值 输入 第一行输入一个整数n表示测试数据的组数(n<100) 每组测试只有一行,其中有三个正整数a,b,c(1=<a,b,c<=1000000000) 输出 输出a的b次方对c取余之后的结果 样例输入 3 2 3 5 3 100 10 11 12345 12345 样例输出 3 1 10481 算法分析: 大数问题,需要利用快速幂取模算法. 所谓的快速幂,实际上是快速幂取模的缩

组合数求模

适用于mod为素数 o(N) void init() { int i; pp[0] = 1; for(i = 1; i <= N-10 ; i++) { pp[i] = (pp[i-1]*i)%mod; } } LL fastmod(LL a,LL k) { LL b = 1; while(k) { if(k&1) b = a*b%mod; a = (a%mod)*(a%mod)%mod; k/=2; } return b; } LL calc(int n,int m) { return (

求模和求余(附加C语言实现)

求模和求余的总体计算步骤如下: 1.求整数商  c = a/b 2.计算模或者余数 r = a - c*b 求模和求余的第一步不同,求余在取c的值时向0方向舍入;取模在计算c的值时向无穷小方向舍入. C语言实现 //取余 int rem(int a, int b) { int c = a * 1.0 / b; return (a - c * b); } //求模 int mod(int a, int b) { int c = floor(a * 1.0 / b); //#include <mat

NYOJ--102--次方求模(快速求幂取模)

次方求模 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 求a的b次方对c取余的值 输入 第一行输入一个整数n表示测试数据的组数(n<100)每组测试只有一行,其中有三个正整数a,b,c(1=<a,b,c<=1000000000) 输出 输出a的b次方对c取余之后的结果 样例输入 3 2 3 5 3 100 10 11 12345 12345 样例输出 3 1 10481 1 /* 2 Name: NYOJ--102--次方求模 3 Copyright: ?

SDUT 2164-Binomial Coeffcients(组合数求模)

Binomial Coeffcients Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 输入 输出 示例输入 3 1 1 10 2 954 723 示例输出 1 45 3557658 提示 来源 山东省第二届ACM大学生程序设计竞赛 详情:组合数求模讲解 #include <stdio.h> #include <math.h> #include <string.h> #include <std

次方求模 NYOJ 102

1 #include<stdio.h>//次方求模(102) 2 long long power(int a,int b,int c) 3 { 4 long long t; 5 if(b==0)return 1%c; 6 if(b==1)return a%c; 7 t=power(a,b/2,c); 8 t=t*t%c; 9 if(b&1)return t*a%c; 10 else return t; 11 } 12 int main() 13 { 14 int x; 15 long

求商求模运算

这两种运算总是感觉有点迷糊,现在 拨开乌云见天日. 对于整型数a,b来说,取模运算或者求余运算的方法都是: 1.求 整数商: c = a/b; 2.计算模或者余数: r = a - c*b. #include <iostream> using namespace std; void div(){ printf("5/3: %d",5/3);cout << endl; printf("5/(-3): %d",5/-3);cout <<