如何获取聚合/分组查询的组成行?
我正在尝试实现一个接口来翻转行项目的布尔状态,
在使用聚合的行集时,我陷入了更新底层行的正确方法。
表格
declare @item table(
id int not null primary key,
amount money not null,
is_paid bit not null,
client varchar(10) not null)
insert into @item values
(1, 9.50, 0, 'Client A'),
(2, 11.50, 0, 'Client A'),
(3, 20.00, 1, 'Client B')
查询
select sum(amount) as total_amount, is_paid, client
from @item
group by is_paid, client
结果
场景
现在假设上面的结果位于一个网格中,如果 is_paid=0,则带有“支付”按钮。
一行映射到单击“付款”后要更新的一行或多行的 ID 。
我的第一个想法是像这样更新:
update @item
set is_paid=1
where client='Client A'
但是,当在显示界面的时间和用户按下“支付”的时间之间插入“客户端 A”的附加行时,这种情况就会崩溃(如果我错了,请纠正我) ”。
问题:由于这似乎是一个相当简单的场景,处理它的典型方法是什么?到目前为止我唯一能想到的就是将聚合/分组移至应用程序逻辑。
I'm trying to implement an interface to flip the boolean status of line items
I'm stuck on the right way to update the underlying rows when working with a rowset that is an aggreate.
Table
declare @item table(
id int not null primary key,
amount money not null,
is_paid bit not null,
client varchar(10) not null)
insert into @item values
(1, 9.50, 0, 'Client A'),
(2, 11.50, 0, 'Client A'),
(3, 20.00, 1, 'Client B')
Query
select sum(amount) as total_amount, is_paid, client
from @item
group by is_paid, client
Result
Scenario
Now say the above results were in a grid with a "Pay" button in if is_paid=0.
A row maps to the IDs of one or more rows to be updated as a result of clicking "Pay".
My first thought was to update like this:
update @item
set is_paid=1
where client='Client A'
But that falls apart (correct me if i'm wrong) the minute an additional row for "Client A" is inserted in between the time the interface is displayed and the time the user presses "Pay".
QUESTION: Since this seems to be a rather simple scenario, what is the typical way to handle it? The only thing I can think of so far is to move the aggregation/grouping to application logic.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以创建临时表来存储 client_id 和 item_id。然后通过将该表与您的项目表连接来选择聚合。这样,当 is_paid = 1 时,您只能更新 item 表中在临时表中具有对应记录的记录。例如:
或者,您可以向
@item
添加create_time
列。这样,您只能更新在特定时间之前创建的那些。例如:You could create at temporary table to store the client_id and item_id. Then select the aggregate by joining that table with your item table. This way, when is_paid = 1, you can update only records in item table that has a corresponding record in the temp table. eg:
Alternatively, you could added a
create_time
column to@item
. This way, you can update only those created before a specific time. eg:您担心在读取数据和更新数据之间数据可能会发生变化吗?
您将需要以可重复读取隔离级别启动事务(我认为)。
http://msdn.microsoft.com/en-我们/库/aa259216(v=sql.80).aspx
You are worried that between the time you read the data and update the data it might change?
You will need to start a transaction with REPEATABLE READ isolation level (I think).
http://msdn.microsoft.com/en-us/library/aa259216(v=sql.80).aspx
你的模式是错误的。您需要第三个链接表来存储客户端 ID 和客户端名称,然后在项目表中存储 clientID 列。然后您可以正确更新:
Your schema is wrong. You need a third linking table that stores a client ID and the client name, and then a clientID column in your item table. You can then update properly:
我对此提出了自己的答案,我没有看到它的缺点,但是我欢迎任何人指出它。
我喜欢的是如何准确地知道要更新哪些行。
我不喜欢的是我花了半天多的时间才让这段代码正常工作,因为我正在与(对我来说)针对 sql server 托管的 clr 进行编程的奇怪现象作斗争。
无论如何,我做了一个聚合,将逗号分隔的 ID 列表直接放入我的查询中。
I rolled my own answer for this one, and I don't see the downside to it, however I'll welcome anyone pointing it out.
What I like is how I know exactly which rows to update.
What I don't like is that it took me more than half a day to get this code working because I was fighting with (to me) the oddities that go with programming against the sql server hosted clr.
Anyway I made an aggregate that puts a comma separated list of IDs right into my query.