请赐教一SQL

Free_Windy 2009-04-24 09:17:05
记录如下:
1,5,6,7 2008-01-02
3,4,5,5 2008-01-03
3,4,5,8 2008-01-04
2,5,7,8 2008-01-05
6,7,8,9 2008-01-06
6,7,8,9 2008-01-07

现在随意输入几个数字,要从以上找到,日期最近连续不包含输入数字的记录.
如输入:1,2,3
则查出:
2,5,7,8 2008-01-05
6,7,8,9 2008-01-06
6,7,8,9 2008-01-07

输入1,2,5
则查出:
6,7,8,9 2008-01-06
6,7,8,9 2008-01-07


...全文
283 45 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
45 条回复
切换为时间正序
请发表友善的回复…
发表回复
lsd123 2009-04-24
  • 打赏
  • 举报
回复
.
liangCK 2009-04-24
  • 打赏
  • 举报
回复
[Quote=引用 41 楼 Free_Windy 的回复:]
39楼完全正确了.
谢谢liangCK 今天的热心帮忙.

但现在还有个问题.
我的数据库是 access
你看能否让其在access
也能运行?
[/Quote]

Access不能运行这个...

对Access不太了解..
Free_Windy 2009-04-24
  • 打赏
  • 举报
回复
39楼完全正确了.
谢谢liangCK 今天的热心帮忙.

但现在还有个问题.
我的数据库是 access
你看能否让其在access
也能运行?
liangCK 2009-04-24
  • 打赏
  • 举报
回复
38楼是为"最近"指定一个范围的..

39楼..完全是按你描述的...
liangCK 2009-04-24
  • 打赏
  • 举报
回复
---------------------------------
-- Author: liangCK 小梁
---------------------------------

--> 生成测试数据: @T
CREATE TABLE T(t1 INT,t2 INT,t3 INT,t4 INT,t5 DATETIME)
INSERT INTO T
SELECT 1,5,6,7,'2008-01-02' UNION ALL
SELECT 3,4,5,5,'2008-01-03' UNION ALL
SELECT 3,4,5,8,'2008-01-04' UNION ALL
SELECT 4,5,7,8,'2008-01-05' UNION ALL
SELECT 6,7,8,9,'2008-01-06' UNION ALL --这里改改
SELECT 6,7,8,9,'2008-01-07'

--SQL查询如下:

GO
CREATE PROC p @str VARCHAR(20)
AS
SELECT *,CAST(NULL AS INT) AS flag INTO #T
FROM T AS A
WHERE CHARINDEX(','+RTRIM(t1)+',',','+@str+',')<=0
AND CHARINDEX(','+RTRIM(t2)+',',','+@str+',')<=0
AND CHARINDEX(','+RTRIM(t3)+',',','+@str+',')<=0
AND CHARINDEX(','+RTRIM(t4)+',',','+@str+',')<=0
AND NOT EXISTS(
SELECT * FROM T
WHERE t5>A.t5
AND (CHARINDEX(','+RTRIM(t1)+',',','+@str+',')>0
OR CHARINDEX(','+RTRIM(t2)+',',','+@str+',')>0
OR CHARINDEX(','+RTRIM(t3)+',',','+@str+',')>0
OR CHARINDEX(','+RTRIM(t4)+',',','+@str+',')>0)

)

DECLARE @min_dt DATETIME;

SET @min_dt=(SELECT MIN(t5) FROM #T)-1;

DECLARE @flag INT;
SET @flag=0;

UPDATE #T SET
@flag=CASE WHEN @min_dt=t5-1 THEN @flag ELSE @flag+1 END,
@min_dt=t5,
flag=@flag;

SELECT B.*
FROM (
SELECT MAX(flag) AS flag
FROM (
SELECT MAX(flag) AS flag FROM #T GROUP BY flag HAVING COUNT(*)>1
) AS T
) AS A
JOIN #T AS B
ON A.flag=B.flag;

DROP TABLE #T;
GO

EXEC p '1,2,3'

EXEC p '1,2,5'

EXEC p '1,2'

EXEC p '1,6'

GO

DROP TABLE T
DROP PROC p

/*
t1 t2 t3 t4 t5 flag
----------- ----------- ----------- ----------- ----------------------- -----------
4 5 7 8 2008-01-05 00:00:00.000 0
6 7 8 9 2008-01-06 00:00:00.000 0
6 7 8 9 2008-01-07 00:00:00.000 0

(3 行受影响)

t1 t2 t3 t4 t5 flag
----------- ----------- ----------- ----------- ----------------------- -----------
6 7 8 9 2008-01-06 00:00:00.000 0
6 7 8 9 2008-01-07 00:00:00.000 0

(2 行受影响)

t1 t2 t3 t4 t5 flag
----------- ----------- ----------- ----------- ----------------------- -----------
3 4 5 5 2008-01-03 00:00:00.000 0
3 4 5 8 2008-01-04 00:00:00.000 0
4 5 7 8 2008-01-05 00:00:00.000 0
6 7 8 9 2008-01-06 00:00:00.000 0
6 7 8 9 2008-01-07 00:00:00.000 0

(5 行受影响)


t1 t2 t3 t4 t5 flag
----------- ----------- ----------- ----------- ----------------------- -----------

(0 行受影响)

*/
liangCK 2009-04-24
  • 打赏
  • 举报
回复
---------------------------------
-- Author: liangCK 小梁
---------------------------------

--> 生成测试数据: @T
CREATE TABLE T(t1 INT,t2 INT,t3 INT,t4 INT,t5 DATETIME)
INSERT INTO T
SELECT 1,5,6,7,'2008-01-02' UNION ALL
SELECT 3,4,5,5,'2008-01-03' UNION ALL
SELECT 3,4,5,8,'2008-01-04' UNION ALL
SELECT 4,5,7,8,'2008-01-05' UNION ALL
SELECT 6,7,8,9,'2008-01-07' UNION ALL --这里改改
SELECT 6,7,8,9,'2008-01-08'

--SQL查询如下:

GO
CREATE PROC p @str VARCHAR(20),@day INT --后几天
AS
SELECT *,CAST(NULL AS INT) AS flag INTO #T
FROM T AS A
WHERE CHARINDEX(','+RTRIM(t1)+',',','+@str+',')<=0
AND CHARINDEX(','+RTRIM(t2)+',',','+@str+',')<=0
AND CHARINDEX(','+RTRIM(t3)+',',','+@str+',')<=0
AND CHARINDEX(','+RTRIM(t4)+',',','+@str+',')<=0
AND NOT EXISTS(
SELECT *
FROM T AS B
WHERE t5 > DATEADD(day,@day-1,A.t5)
AND (CHARINDEX(','+RTRIM(t1)+',',','+@str+',')>0
OR CHARINDEX(','+RTRIM(t2)+',',','+@str+',')>0
OR CHARINDEX(','+RTRIM(t3)+',',','+@str+',')>0
OR CHARINDEX(','+RTRIM(t4)+',',','+@str+',')>0)
)

DECLARE @min_dt DATETIME;

SET @min_dt=(SELECT MIN(t5) FROM #T)-1;

DECLARE @flag INT;
SET @flag=0;

UPDATE #T SET
@flag=CASE WHEN @min_dt=t5-1 THEN @flag ELSE @flag+1 END,
@min_dt=t5,
flag=@flag;

SELECT B.*
FROM (
SELECT MAX(flag) AS flag
FROM (
SELECT MAX(flag) AS flag FROM #T GROUP BY flag HAVING COUNT(*)>1
) AS T
) AS A
JOIN #T AS B
ON A.flag=B.flag;

DROP TABLE #T;
GO

EXEC p '1,2,5',2 --后两天没出现过1,2,5

GO

DROP TABLE T
DROP PROC p
liangCK 2009-04-24
  • 打赏
  • 举报
回复
[Quote=引用 36 楼 liangCK 的回复:]
引用 34 楼 Free_Windy 的回复:
范围?
就是你要查的出现过的最后一个记录的后面所有记录.这个范围是要看你查哪个数字了


如 (从上往下,1是出现在最早,6是出现在最近,按顺序)
1
4
3
5
4
4
5
5
6
最近没出现过5的就只有6了(最近出现过5,后面只有6)
最近没出现过4的就只有5,5,6 (最近出现过4,后面只有5,5,6)
最近没出现过6的就不存在了(最近出现过6,后面不存在)

这个例子,我想应该可以表达清楚了.
[/Quote]

这个叫比当前行(日期)往后的数据没出现过当前数据的记录..
liangCK 2009-04-24
  • 打赏
  • 举报
回复
[Quote=引用 34 楼 Free_Windy 的回复:]
范围?
就是你要查的出现过的最后一个记录的后面所有记录.这个范围是要看你查哪个数字了


如 (从上往下,1是出现在最早,6是出现在最近,按顺序)
1
4
3
5
4
4
5
5
6
最近没出现过5的就只有6了(最近出现过5,后面只有6)
最近没出现过4的就只有5,5,6 (最近出现过4,后面只有5,5,6)
最近没出现过6的就不存在了(最近出现过6,后面不存在)

这个例子,我想应该可以表达清楚了.
[/Quote]

你这个叫个鸟最近啊.
liangCK 2009-04-24
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 liangCK 的回复:]
你的最近还是有歧意的吧?..

要就只往后查??
如果查1,2,,现在2001年出现了1,那2001年到2009年都不能出现1,2了吗?..

你的最近起码有个范围才能叫最近吧??
[/Quote]

偶想偶这里也说得很清楚了..

这个最近..到底是几天才叫最近呢???

是前后1000000天叫最近.还是前后2天叫最近呢?
Free_Windy 2009-04-24
  • 打赏
  • 举报
回复
范围?
就是你要查的出现过的最后一个记录的后面所有记录.这个范围是要看你查哪个数字了


如 (从上往下,1是出现在最早,6是出现在最近,按顺序)
1
4
3
5
4
4
5
5
6
最近没出现过5的就只有6了(最近出现过5,后面只有6)
最近没出现过4的就只有5,5,6 (最近出现过4,后面只有5,5,6)
最近没出现过6的就不存在了(最近出现过6,后面不存在)

这个例子,我想应该可以表达清楚了.
liangCK 2009-04-24
  • 打赏
  • 举报
回复
你的最近起码有个范围才能叫最近吧??
Free_Windy 2009-04-24
  • 打赏
  • 举报
回复

1
4
3
5
4
4
5
5
6
最近没出现过5的就只有6了(最近出现过5,后面只有6)
最近没出现过4的就只有5,5,6 (最近出现过4,后面只有5,5,6)
最近没出现过6的就不存在了(最近出现过6,后面不存在)


汗,这个可能是我表达得不是很清淅!!!!不好意思
liangCK 2009-04-24
  • 打赏
  • 举报
回复
你的最近起码有个范围才能叫最近吧??
Free_Windy 2009-04-24
  • 打赏
  • 举报
回复

1
4
3
5
4
4
5
5
6
最近没出现过5的就只有6了
最近没出现过4的就只有5,5,6
最近没出现过6的就不存在了
liangCK 2009-04-24
  • 打赏
  • 举报
回复
所以你不用再说买彩票的了..这里没人买过彩票.
liangCK 2009-04-24
  • 打赏
  • 举报
回复
你的最近还是有歧意的吧?..

要就只往后查??
如果查1,2,,现在2001年出现了1,那2001年到2009年都不能出现1,2了吗?..

你的最近起码有个范围才能叫最近吧??
Free_Windy 2009-04-24
  • 打赏
  • 举报
回复

t1,t2,t3,t4,t5
1,5,6,7,2008-01-02 00:00:00.000
3,4,5,5,2008-01-03 00:00:00.000
3,4,5,8,2008-01-04 00:00:00.000
4,5,7,8,2008-01-05 00:00:00.000
6,7,8,9,2008-01-06 00:00:00.000
6,7,8,9,2008-01-07 00:00:00.000

最近也就是说,
如果要查的数字5,那么,第4条记录中有出现5,我们就要从那条记录算起往后查.
满足的就:
6,7,8,9,2008-01-06 00:00:00.000
6,7,8,9,2008-01-07 00:00:00.000

如果要查的数字1,那么,第1条记录中有出现1,我们就要从那条记录算起往后查.
3,4,5,5,2008-01-03 00:00:00.000
3,4,5,8,2008-01-04 00:00:00.000
4,5,7,8,2008-01-05 00:00:00.000
6,7,8,9,2008-01-06 00:00:00.000
6,7,8,9,2008-01-07 00:00:00.000

如果要查的数字9,那么,第6条(最后一条)记录中有出现9,我们就要从那条记录算起往后查.

不存在记录


---------------------------
其实我们可以想像为我们去买采票
我们现在要选几个码,但我想知道最近多少期没开过这些码.
这样可能更好理解
liangCK 2009-04-24
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 Free_Windy 的回复:]
很明显,基础数据中最近日期(6,7,8,9,2008-01-07 00:00:00.000)中存在一个 6
我们查来的记录应该为空才对的
[/Quote]

请问你的最近..多近才叫最近呢?
qixiang 2009-04-24
  • 打赏
  • 举报
回复
看不懂
Free_Windy 2009-04-24
  • 打赏
  • 举报
回复
liangCK 太感谢你了
我刚才测试一下你的代码发现有个问题



基础数据
t1,t2,t3,t4,t5
1,5,6,7,2008-01-02 00:00:00.000
3,4,5,5,2008-01-03 00:00:00.000
3,4,5,8,2008-01-04 00:00:00.000
4,5,7,8,2008-01-05 00:00:00.000
6,7,8,9,2008-01-06 00:00:00.000
6,7,8,9,2008-01-07 00:00:00.000

执行:
SELECT*FROM T
EXEC p '1,6'

查出的数据:
t1,t2,t3,t4,t5,flag
3,4,5,5,2008-01-03 00:00:00.000,0
3,4,5,8,2008-01-04 00:00:00.000,0
4,5,7,8,2008-01-05 00:00:00.000,0

(所影响的行数为 3 行)

很明显,基础数据中最近日期(6,7,8,9,2008-01-07 00:00:00.000)中存在一个 6
我们查来的记录应该为空才对的
加载更多回复(25)

22,301

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧