根据选定列中的相同值向行添加数字
Posted
技术标签:
【中文标题】根据选定列中的相同值向行添加数字【英文标题】:Add number to rows based on identical values in selected columns 【发布时间】:2012-03-08 03:57:21 【问题描述】:我有一个 PostgreSQL 数据库,其中包含由几个司法管辖区编写的交通罚单。
一些司法管辖区没有说明是否在一个交通站点中写入了多张罚单。但是,这可以通过分析其他领域来推断。考虑这些数据:
ticket_id timestamp drivers_license
----------------------------------------------
1 2008-08-07 01:51:00 11111111
2 2008-08-07 01:51:00 11111111
3 2008-08-07 02:02:00 22222222
4 2008-08-07 02:25:00 33333333
5 2008-08-07 04:23:00 44444444
6 2008-08-07 04:23:00 55555555
7 2008-08-07 04:23:00 44444444
我可以推断:
票 1 和 2 写在一个交通站,因为它们共享驾驶执照号码和时间戳。 5 和 7 相同,但请注意票 6 在它们之间的位置。也许另一名官员同时在其他地方写了一张罚单,或者数据输入操作员输入了乱序的东西。我想为每个交通站点添加另一个具有唯一 ID 的列。它不会是表的主键,因为它会有重复的值。例如:
ticket_id timestamp drivers_license stop_id
--------------------------------------------------------
1 2008-08-07 01:51:00 11111111 1
2 2008-08-07 01:51:00 11111111 1
3 2008-08-07 02:02:00 22222222 2
4 2008-08-07 02:25:00 33333333 3
5 2008-08-07 04:23:00 44444444 4
6 2008-08-07 04:23:00 55555555 5
7 2008-08-07 04:23:00 44444444 4
我可以想到用 C# 执行此操作的计算密集型、贪心算法的方法,但是是否有有效的 SQL 查询可以工作?
【问题讨论】:
我看不出简单地添加另一列与已经拥有驾驶执照的外键有什么不同... 时间戳不同。 是的。可以在不同场合引用单个驾驶者(单个 DL)。 【参考方案1】:如果您使用window function rank()
,这将变得非常简单:
SELECT *
,rank() OVER (ORDER BY ts, drivers_license)
FROM tbl
ORDER BY ticket_id
准确地返回您要求的内容。
我将您的列 timestamp
重命名为 ts
,因为 timestamp
在 PostgreSQL 中是一个类型名称,在每个 SQL 标准中都是一个 reserved word。
【讨论】:
【参考方案2】:高效的 SQL 查询 FTW!
我不在可以测试它的计算机上,因此可能存在一些语法问题;我会在早上修复,但它是这样的:
WITH uniquez as (SELECT timestamp, drivers_license,
rank() over (ORDER BY timestamp, drivers_license) as counterz
FROM ticketTable)
UPDATE ticketTable TT
SET stop_id = uniquez.counterz
WHERE uniquez.timestamp = TT.timestamp
AND uniquez.drivers_license = TT.drivers_license
基本上,您可以选择按时间戳和 drivers_license 分组(分区),并有一个与之配套的行计数器。当您进行更新时,您使用这个先前选择表的行计数器作为您的“stop_id”并更新与时间戳和驾驶执照匹配的列。
【讨论】:
无论 postgreSQL 是否允许,在没有 ORDER BY 子句的情况下使用 ROW_NUMBER() 是一个非常糟糕的主意。无论如何,我认为您在这里所拥有的根本不起作用。如果按时间戳、drivers_license 分区,则每次时间戳、drivers_license 更改时,行编号都会再次从 1 开始。如果您将 partition by 更改为 ORDER BY,您会更接近,但我认为您需要 DENSE_RANK(),而不是 row_number()。 @SteveKass 绝对同意。深夜编程会对事情产生这种影响。我会编辑。 -1 您只是将我的正确版本复制到不正确的版本上,而没有注明。这不是这里推荐的方式 - 礼貌地说。 我在基于此构建的查询中遇到了一个奇怪的错误。我在***.com/questions/9643859/… 开了一个单独的问题。 原来您在 UPDATE 语句中缺少 FROM 子句。在 SET 行之后,您需要一个 FROM uniquez。【参考方案3】:您最好的选择可能是创建一个带有 DISTINCT 时间戳和驾驶执照编号的新表(例如“stops”),分配行号,然后从该新表更新票证表。
【讨论】:
【参考方案4】:SELECT ticket_id,timestamp,drivers_license,substr(drivers_license,1,1) as stop_id
FROM traffic_data;
希望这对你有用... :)
【讨论】:
一个人可能会在不同的站点收到不同的票,所以很遗憾,这行不通。以上是关于根据选定列中的相同值向行添加数字的主要内容,如果未能解决你的问题,请参考以下文章