仍然让我的头脑加入这样的事情。
这是我的问题......
我们有一个表格,其中包含有关特定"昵称"的大量信息,这是在我们销售产品时输入的。遗憾的是,除了昵称之外,没有办法将记录与相同的昵称绑在一起。
每行中的一个值是产品售出时的货架编号。
我们之前没有使用过这些信息,但现在我们想要添加一个新行,其中还包括产品上次售出时的货架编号。
这对于新记录来说不是一个大问题,因为我使用ASP来添加记录,并且可以轻松地进行最后一次记录更新以获取值。
问题是我们想要超过220,000条记录并执行相同的操作,虽然我已经在ASP中编写了一个脚本来执行此操作...即使我已经将脚本分解为运行,它也会永远运行一次销售一天(ASP Classic)。
所以我很想知道在Microsoft SQL Server 12上是否存在SQL等价物。
新纪录|昵称|架子|最后一个架子
2152 | '老橘子' | 10 | 9
您知道每条记录都有唯一的ID和日期戳。
问题进一步复杂化,因为有时产品不会在销售期间出售,因此最后一条记录可能包含空值而非数字。在这种情况下,我想忽略这个记录,如果有一个记录,那就转到那个记录。
如果你能提供帮助,谢谢你。
MALC
答案 0 :(得分:0)
更改此答案以提供触发器和示例更新,以设置现有数据的最后一个数据库。已修改SQL以添加此内容。
我能想到的最简单的解决方案是使用插入触发器。这是一个可以在非生产SQL服务器上运行的测试脚本。我在触发器中使用了一些代码,这些代码适用于MS SQL Server 2005或更高版本(用于分区的' over'子句)。我在SQL 2008上测试过它,但没有在任何其他版本或SQLexpress上测试过。
我在datestamp列中添加了,因为需要知道哪条记录是最新的。
触发器中的逻辑是排除新记录,并查找具有最新日期戳和最高ID的项目。如果同一昵称的两个项目存在于同一日期,则它使用id最高的值。它排除任何货架为空的项目。
在表格中,我还添加了一个名为' expected'存储我期望LastShelf列包含该行的内容。在我的测试中,他们都匹配。
如果在具有相同昵称的多个项目的单个SQL语句中进行批量插入,则LastShelf将来自现有数据,并且不会获取插入数据中的任何Shelf值。也许某种SQL专家可以建议重写我的insert语句来解决这个问题吗?
希望这会有所帮助..
-- Create a demo database (
use master;
go
create database [Demo_Trigger];
go
use Demo_Trigger;
-- Create the table we want to test
create table Items
(ID int not null identity primary key, -- primary key
datestamp datetime not null, -- timestamp of record (to find last entry)
nickname nvarchar(64) not null, -- nickname
shelf int null, -- shelf (can be null)
lastShelf int null, -- last shelf
expected int null); -- for testing/demo - what we expect result to be!
GO
-- Create an insert trigger
create trigger Items_InsertSetLastShelf
on Items after Insert as
BEGIN
SET NOCOUNT ON;
-- determine unique list of nicknames being inserted
update Items
Set LastShelf = tmp.Shelf
from Items,
(
select nickname, shelf from
(
select id, nickname, datestamp, shelf,
MAX(datestamp) over (partition by nickname) maxDate, -- get latest by date
MAX(id) over (partition by nickname) maxID -- get highest id
from items
where shelf is not null -- ignore null shelf
and nickname in (select distinct nickname from inserted) -- only search for inserted nicknames
and items.id not in (select id from inserted) -- exclude new records
) tmp2
where datestamp = maxdate and id = maxID
) tmp
where Items.nickname = tmp.Nickname and items.ID IN (SELECT ID from inserted)
END;
GO
-- create some items to test functionality
insert items (datestamp, nickname, shelf, expected) values ('2014-01-01','aaa',1, null); -- aaa on shelf 1
insert items (datestamp, nickname, shelf, expected) values ('2014-01-01','aaa',2, 1); -- aaa on shelf 2 but same date as previous
insert items (datestamp, nickname, shelf, expected) values ('2014-01-02','bbb',2, null); -- bbb on shelf 2, no prev record
insert items (datestamp, nickname, shelf, expected) values ('2014-01-03','aaa',3, 2); -- aaa - should have lastShelf=2, as that was the last record, not 1
insert items (datestamp, nickname, shelf, expected) values ('2014-01-04','aaa',null, 3); -- aaa again, but null shelf, lastShelf=3
insert items (datestamp, nickname, shelf, expected) values ('2014-01-06','aaa',4, 3); -- aaa last shelf should ignore null, still 3
insert items (datestamp, nickname, shelf, expected) values ('2014-01-08','bbb',1, 2); -- bbb lastShelf=2
insert items (datestamp, nickname, shelf, expected) values ('2014-01-06','aaa',5, 4); -- aaa lastShelf should be 4
-- show results
select * from Items;
此时,项目是正确的,所以现在删除LastShelf以模拟现有记录:
update Items set LastShelf =null;
此查询将为现有记录设置LastShelf值:工具架不能为空,具有相同的昵称以及更早的日期和更低的ID。对于具有相同日期的条目,使用来自较高ID的货架。您可以通过比较"预期"来检查结果。最后一个架子。
update Items
set lastShelf = tmp.computed
from (
select i1.ID, i1.Nickname, i1.shelf, i1.expected,
(select top 1 i3.shelf from
(
select id, nickname, datestamp, shelf,
MAX(datestamp) over (partition by nickname) maxDate, -- get latest by date
MAX(id) over (partition by nickname) maxID -- get highest id
from items i2
where i2.shelf is not null -- ignore null shelf
and i2.nickname = i1.nickname -- same nickname
and i2.datestamp <= i1.datestamp -- date is earlier than this record
and i2.ID < i1.ID -- ID is lower than this record
) i3 where i3.maxDate = i3.datestamp and i3.ID = i3.maxID
) computed
from Items i1
) tmp where Items.ID = tmp.ID;