为具有相同数据组合的行分配相同的id

时间:2016-02-15 10:32:23

标签: sql postgresql

我有一个包含多列的表格,其中文件夹 seq_no 字段用作记录的标识方法。我想为那些组合相同的记录分配相同的id,并且(如果可能的话)id的总数必须是顺序的,以充分利用id列值。一个例子:

+-----+-----+------+------+-----+
|  id |year |folder|seq_no|count|
+=====+=====+======+======+=====+
|  1  |1973 |  5   |  11  |  2  | << 1973, 5, 11
+-----+-----+------+------+-----+
|  2  |2010 |  4   |  7   |  2  | << 2010, 4, 7
+-----+-----+------+------+-----+
|  3  |1973 |  11  |  12  |  1  | << 1973, 11, 12
+-----+-----+------+------+-----+
|  1  |1973 |  5   |  11  |  2  | << 1973, 5, 11
+-----+-----+------+------+-----+
|  4  |1500 |  4   |  7   |  1  | << 1500, 4, 7
+-----+-----+------+------+-----+
|  2  |2010 |  4   |  7   |  2  | << 2010, 4, 7
+-----+-----+------+------+-----+

但是,我更喜欢在php部分中不通过计算分配id,而是每个新条目上的表本身检查此条目是否与其他条目具有相同的组合。如果是,请指定相同的ID。如果没有,请指定下一个可用ID。

另外,我想计算每行有多少具有相同ID的记录,这也应该自动完成。

我在想使用触发器或功能......不知道该怎么做。

3 个答案:

答案 0 :(得分:2)

在查询时执行:

with t (year, folder, seq_no) as (values
    (1973,5,11),
    (2010,4,7),
    (1973,11,12),
    (1973,5,11),
    (1500,4,4),
    (2010,4,7)
)
select
    dense_rank() over (order by year, folder, seq_no) as id,
    year, folder, seq_no,
    count(*) over (partition by year, folder, seq_no) as "count"
from t
;
 id | year | folder | seq_no | count 
----+------+--------+--------+-------
  1 | 1500 |      4 |      4 |     1
  2 | 1973 |      5 |     11 |     2
  2 | 1973 |      5 |     11 |     2
  3 | 1973 |     11 |     12 |     1
  4 | 2010 |      4 |      7 |     2
  4 | 2010 |      4 |      7 |     2

答案 1 :(得分:1)

我不会尝试在表格中存储此类ID,尤其是COUNT。

想象一下,在您的示例中,您希望再插入一行

+-----+------+------+
|year |folder|seq_no|
+-----+------+------+
|1973 |  5   |  11  |
+-----+------+------+

服务器必须找到具有相同组合的所有现有行,并使用新值COUNT更新它们。

每个INSERTUPDATEDELETE变得非常昂贵。

这些信息可以在需要时使用DENSE_RANKCOUNT来计算:

SELECT
    year
    ,folder
    ,seq_no
    ,DENSE_RANK() OVER(ORDER BY year, folder, seq_no) AS ID
    ,COUNT(*) OVER(PARTITION BY year, folder, seq_no) AS cnt
FROM YourTable

答案 2 :(得分:0)

您可以在多列上构建唯一的索引,如下所示:

CREATE UNIQUE INDEX year_folder_seqNo ON my_table (year, folder, seq_no);

这将阻止多个插入具有相同的值(因此每个组合只有1行)