根据所选列中的相同值向行添加数字

时间:2012-03-08 03:57:21

标签: sql postgresql aggregate-functions window-functions

我有一个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查询可以工作吗?

4 个答案:

答案 0 :(得分:3)

如果您使用window function rank(),这变得非常简单:

SELECT *
      ,rank() OVER (ORDER BY ts, drivers_license)
FROM   tbl
ORDER  BY ticket_id

准确地返回您要求的内容。

我将您的专栏timestamp重命名为ts,因为timestamp是PostgreSQL中的类型名称,并且是每个SQL标准中的reserved word

答案 1 :(得分:1)

可能你最好的办法是用DISTINCT时间戳和驾驶执照#s创建一个新表(比如“停止”),分配行号,然后从新表中更新票证表。

答案 2 :(得分:1)

高效的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

基本上,您通过timestamp和drivers_license进行组(分区)的选择,并具有与之一致的行计数器。执行更新时,将此前一个选择表的行计数器用作“stop_id”,并更新与时间戳和驱动程序许可证匹配的列。

答案 3 :(得分:-1)

SELECT ticket_id,timestamp,drivers_license,substr(drivers_license,1,1) as stop_id
FROM traffic_data;

希望这对你有用......:)