特别具有挑战性的SQL问题。 [英] Particularly Challenging SQL Problem.

查看:74
本文介绍了特别具有挑战性的SQL问题。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

表DDL:


创建表测试



inId int主键身份,

inFK int not null,

inSeq int not null,

dtDate datetime




数据插入:

插入测试

选择1,1,getdate()


WAITFOR DELAY''000:00 :01''


插入测试

选择1,1,getdate()


WAITFOR DELAY' '000:00:01''


插入测试

选择1,1,getdate()


WAITFOR DELAY''000:00:01''


插入测试

选择2,1,getdate()

WAITFOR DELAY''000:00:01''


插入测试

选择2,1,getdate()


WAITFOR DELAY''000:00:01''


插入测试

选择3,1,getdate( )


等待延迟''000:00:01''


插入测试

选择4,1,getdate()

如果我们选择此表:

inId inFK inSeq dtDate


----------- ----------- -----------

------ ------------------------------------------------ <无线电通信/>
1 1 1 2005-02-01 12:54:40.967

2 1 1 2005-02-01 12:54:41.967

3 1 1 2005-02-01 12:54:42.967

4 2 1 2005-02-01 12:54:43.967

5 2 1 2005-02-01 12: 54:44.967

6 3 1 2005-02-01 12:54:45.983

7 4 1 2005-02-01 12:54:47.077


(7行受影响)

问题:

我想要做的事情(使用SQL而不是游标)是要更新的inSeq对其序数位置的
值,这将基于inFK的

出现次数。例如,我想运行一个sql语句

将数据转换为:


更新测试

设置在SEQ中=(某些sql)


select * from test - 这将产生:


inId inFK inSeq dtDate

>
----------- ----------- -----------

---- --------------------------------------------------

1 1 1 2005-02-01 12:54:40.967

2 1 2 2005-02-01 12:54:41.967

3 1 3 2005-02-01 12:54:42.967

4 2 1 2005-02-01 12:54:43.967

5 2 2 2005-02-01 12:54:44.967

6 3 1 2005-02-01 12:54:45.983

7 4 1 2005-02-01 12:54:47.077
(7排受影响)

我们将非常感谢任何帮助。


TFD

解决方案




如果插入记录,以下解决方案将有效

相同的inFK值)仅按顺序排列。


更新测试集inSeq =(inid - (从测试b中选择min(inid)其中

a.infk = b.infk)+ 1)来自测试a


谢谢

Ssk


如果记录是

LineVoltageHalogen写道:

表DDL:

创建表测试

inId int主键标识,
inFK int not null,
inSeq int not null,
dtDate datetime


数据插入:
插入测试
选择1,1,getdate()

WAITFOR DELAY''000:00:01''

插入测试
选择1,1,getdate()

WAITFOR DELAY''000:00:01''

插入测试
select 1,1,getdate()

WAITFOR DELAY''000:00:01''

插入测试
选择2,1,getdate()

WAITFOR DELAY''000:00:01''

插入测试
选择2,1,getdate()

WAITFOR DELAY''000:00:01''

插入测试
选择3, 1,getdate()

WAITFOR DELAY''000:00:01''

插入测试
select 4,1,getdate()

如果我们在这张桌子上选择:
inId inFK inSeq dtDate

----------- ----------- -----------
----------------------------------- -------------------
1 1 1 2005-02-01 12:54:40.967
2 1 1 2005-02-01 12: 54:41.967
3 1 1 2005-02-01 12:54:42.967
4 2 1 2005-02-01 12:54:43.967
5 2 1 2005-02-01 12 :54:44.967
6 3 1 2005-02-01 12:54:45.983
7 4 1 2005-02-01 12:54:47.077

(7行受影响)

问题:
我想做什么(使用SQL和不是游标)是将inSeq的
值更新为其序数位置,这将基于inFK出现的#
。例如,我想运行一个sql
语句,将数据转换为:

更新测试
设置在SEQ =(某些sql)
select * from test - 这将产生:

inId inFK inSeq dtDate

----------- -------- --- -----------
-------------------------------- ----------------------
1 1 1 2005-02-01 12:54:40.967
2 1 2 2005-02- 01 12:54:41.967
3 1 3 2005-02-01 12:54:42.967
4 2 1 2005-02-01 12:54:43.967
5 2 2 2005-02 -01 12:54:44.967
6 3 1 2005-02-01 12:54:45.983
7 4 1 2005-02-01 12:54:47.077
(7行(s)受影响)

非常感谢任何帮助。

TFD




我可以控制你通过在inId上创建一个集群主键,

inFk和sdDate,你同意吗?


TFD


否。聚集索引无关紧要。它对UPDATE语句的标准行为没有影响。

记录的行为。文档中未定义的某些不寻常的

和模糊的UPDATE语句的结果可能会受到索引的影响,但每个语句的行为保持不变

case:结果是未定义的,因此不可靠。


如果inseq完全基于infk和dtdate的值,则没有

显然需要将列放在表中。当您查询表格或在客户端添加编号时,导出序列:


SELECT T1.inid,T1.infk,

COUNT(*)AS inseq,T1.dtdate

来自测试AS T1

加入测试AS T2

ON T1.infk = T2.infk

AND T1.dtdate> = T2.dtdate

GROUP BY T1.inid,T1.infk,T1.dtdate

-

David Portas

SQL Server MVP

-


Table DDL:

create table test
(
inId int primary key identity,
inFK int not null,
inSeq int not null,
dtDate datetime
)

Data Insert:
insert into test
select 1,1, getdate()

WAITFOR DELAY ''000:00:01''

insert into test
select 1,1, getdate()

WAITFOR DELAY ''000:00:01''

insert into test
select 1,1, getdate()

WAITFOR DELAY ''000:00:01''

insert into test
select 2,1, getdate()

WAITFOR DELAY ''000:00:01''

insert into test
select 2,1, getdate()

WAITFOR DELAY ''000:00:01''

insert into test
select 3,1, getdate()

WAITFOR DELAY ''000:00:01''

insert into test
select 4,1, getdate()
If we select on this table:
inId inFK inSeq dtDate

----------- ----------- -----------
------------------------------------------------------
1 1 1 2005-02-01 12:54:40.967
2 1 1 2005-02-01 12:54:41.967
3 1 1 2005-02-01 12:54:42.967
4 2 1 2005-02-01 12:54:43.967
5 2 1 2005-02-01 12:54:44.967
6 3 1 2005-02-01 12:54:45.983
7 4 1 2005-02-01 12:54:47.077

(7 row(s) affected)
Problem:
What I would like to do (using SQL and not a cursor) is to update the
value of inSeq to its ordinal position, this will be based on the # of
occurences of inFK. For Example, I would like to run a sql statement
that would transform the data to:

update test
set inSEQ = (some sql)

select * from test - This would then produce:

inId inFK inSeq dtDate

----------- ----------- -----------
------------------------------------------------------
1 1 1 2005-02-01 12:54:40.967
2 1 2 2005-02-01 12:54:41.967
3 1 3 2005-02-01 12:54:42.967
4 2 1 2005-02-01 12:54:43.967
5 2 2 2005-02-01 12:54:44.967
6 3 1 2005-02-01 12:54:45.983
7 4 1 2005-02-01 12:54:47.077
(7 row(s) affected)
Any help would be greatly appreciated.

TFD

解决方案

Hi

The following solution will work if the inserted records (with
same inFK value ) are in sequential order only.

update test set inSeq = (inid - (select min(inid) from test b where
a.infk = b.infk ) + 1) from test a

Thanks
Ssk

If the Records are
LineVoltageHalogen wrote:

Table DDL:

create table test
(
inId int primary key identity,
inFK int not null,
inSeq int not null,
dtDate datetime
)

Data Insert:
insert into test
select 1,1, getdate()

WAITFOR DELAY ''000:00:01''

insert into test
select 1,1, getdate()

WAITFOR DELAY ''000:00:01''

insert into test
select 1,1, getdate()

WAITFOR DELAY ''000:00:01''

insert into test
select 2,1, getdate()

WAITFOR DELAY ''000:00:01''

insert into test
select 2,1, getdate()

WAITFOR DELAY ''000:00:01''

insert into test
select 3,1, getdate()

WAITFOR DELAY ''000:00:01''

insert into test
select 4,1, getdate()
If we select on this table:
inId inFK inSeq dtDate

----------- ----------- -----------
------------------------------------------------------
1 1 1 2005-02-01 12:54:40.967
2 1 1 2005-02-01 12:54:41.967
3 1 1 2005-02-01 12:54:42.967
4 2 1 2005-02-01 12:54:43.967
5 2 1 2005-02-01 12:54:44.967
6 3 1 2005-02-01 12:54:45.983
7 4 1 2005-02-01 12:54:47.077

(7 row(s) affected)
Problem:
What I would like to do (using SQL and not a cursor) is to update the
value of inSeq to its ordinal position, this will be based on the # of occurences of inFK. For Example, I would like to run a sql statement that would transform the data to:

update test
set inSEQ = (some sql)

select * from test - This would then produce:

inId inFK inSeq dtDate

----------- ----------- -----------
------------------------------------------------------
1 1 1 2005-02-01 12:54:40.967
2 1 2 2005-02-01 12:54:41.967
3 1 3 2005-02-01 12:54:42.967
4 2 1 2005-02-01 12:54:43.967
5 2 2 2005-02-01 12:54:44.967
6 3 1 2005-02-01 12:54:45.983
7 4 1 2005-02-01 12:54:47.077
(7 row(s) affected)
Any help would be greatly appreciated.

TFD




I can probably control this by creating a clusterd primary key on inId,
inFk, and sdDate, do you concur?

TFD


No. A clustered index is irrelevant. It has no impact on the standard,
documented behaviour of an UPDATE statement. The results of certain unusual
and ambiguous UPDATE statements which are undefined in the documentation may
be affected by indexes but the behaviour of those remains the same in each
case: the result is undefined and therefore unreliable.

If inseq is based purely on the values of infk and dtdate then there is no
obvious need to put the column in the table at all. Derive the sequence when
you query the table or add the numbering at client-side:

SELECT T1.inid, T1.infk,
COUNT(*) AS inseq, T1.dtdate
FROM Test AS T1
JOIN Test AS T2
ON T1.infk = T2.infk
AND T1.dtdate >= T2.dtdate
GROUP BY T1.inid, T1.infk, T1.dtdate

--
David Portas
SQL Server MVP
--


这篇关于特别具有挑战性的SQL问题。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆