如果我有一个包含以下列和值的表,按data: datafromNetworking
排序:
parent_id
我想用id parent_id line_no
-- --------- -------
1 2
2 2
3 2
4 3
5 4
6 4
每次更改时从1开始的序列号填充line_no
:
parent_id
查询或存储过程是什么样的?
注意:我应该指出,我只需要这样做一次。我的PHP代码中有一个新函数,每次添加新记录时,该函数都会自动创建id parent_id line_no
-- --------- -------
1 2 1
2 2 2
3 2 3
4 3 1
5 4 1
6 4 2
。我只需要更新已经存在的记录即可。
答案 0 :(得分:1)
或者,是一所老学校...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,parent_id INT NOT NULL
);
INSERT INTO my_table VALUES
(1, 2),
(2 , 2),
(3 , 2),
(4 , 3),
(5 , 4),
(6 , 4);
SELECT x.*
, CASE WHEN @prev = parent_id THEN @i := @i+1 ELSE @i := 1 END i
, @prev := parent_id prev
FROM my_table x
, (SELECT @prev:=null,@i:=0) vars
ORDER
BY parent_id,id;
+----+-----------+------+------+
| id | parent_id | i | prev |
+----+-----------+------+------+
| 1 | 2 | 1 | 2 |
| 2 | 2 | 2 | 2 |
| 3 | 2 | 3 | 2 |
| 4 | 3 | 1 | 3 |
| 5 | 4 | 1 | 4 |
| 6 | 4 | 2 | 4 |
+----+-----------+------+------+
答案 1 :(得分:1)
大多数MySQL版本不支持row_number()
。因此,您可以使用变量来执行此操作。但是您必须非常小心。 MySQL不保证select
中变量的求值顺序,因此不应为变量分配不同表达式中的引用。
所以:
select t.*,
(@rn := if(@p = parent_id, @rn + 1,
if(@p := parent_id, 1, 1)
)
) as line_no
from (select t.* from t order by id) t cross join
(select @p := 0, @rn := 0) params;
可能不需要对表进行排序的子查询。在5.7版附近的某个地方,使用变量时变得很有必要。
编辑:
使用变量更新很有趣。在这种情况下,我只会在上面使用子查询:
update t join
(select t.*,
(@rn := if(@p = parent_id, @rn + 1,
if(@p := parent_id, 1, 1)
)
) as new_line_no
from (select t.* from t order by id) t cross join
(select @p := 0, @rn := 0) params
) tt
on t.id = tt.id
set t.line_no = tt.new_line_no;
答案 2 :(得分:0)
如果row_number()
无效,则可以使用子查询:
select t.*,
(select count(*)
from table t1
where t1.parent_id = t.parent_id and t1.id <= t.id
) as line_no
from table t;