I have the following table (called node_items):
id node_id position
== ======= ========
1 1 1
2 1 1
3 2 1
4 2 1
5 2 1
6 2 1
7 3 1
8 3 1
9 3 1
10 3 1
The position field is supposed to mark an items position in the node. They are currently all set at 1. I am wanting to fix this table by setting an incremental position for each item per node_id. So, the result I am after is:
id node_id position
== ======= ========
1 1 1
2 1 2
3 2 1
4 2 2
5 2 3
6 2 4
7 2 5
8 3 1
9 3 2
10 3 3
So I somehow need to group each item by node_id and set the position to an initial value of 1 and increment it for each subsequent item with that node_id.
Note: To keep my explanation simple, the above node_ids are shown in order (1,1, 2, 2,2,2,2,3,3,3), but this isn't usually the case.
What query can I use to update the position values incrementally for each node_id?
Fixing the table once can be done with an UPDATE:
SET #n = 0, #p = 1;
UPDATE node_items
SET position = (#p := IF(node_id=#n, #p+1, 1)),
node_id = (#n := node_id)
ORDER BY node_id, id;
Making the table maintain the position values as you insert/update/delete data is harder. Basically, can't do it while allowing concurrent updates. You have to lock the table in every session that needs to do writes to the table. This makes concurrent sessions run serially.
You can read my old post about this here: Some sort of “different auto-increment indexes” per a primary key values
Related
Environment :
MySQL 5.7.x
Spring MVC
Table Data (name: TableA)
seq
level
name
order
parent_seq
1
1
name1
1
0
2
1
name2
2
0
3
2
sub1-1
1
1
4
2
sub1-2
2
1
5
2
sub2-1
1
2
6
3
third-2-1
1
5
7
3
third-1-1
1
3
Expected Result
seq
level
name
order
parent_seq
next_level
1
1
name1
1
0
2
3
2
sub1-1
1
1
3
7
3
third-1-1
1
3
2
4
2
sub1-2
2
1
1
2
1
name2
2
0
2
5
2
sub2-1
1
2
3
6
3
third-2-1
1
5
1 (last default value: 1)
Now I'm genenrating expected result with nested for statement(JAVA).
Is there any way to generate expected result only with MySQL Query?
The data stacked in random order in the table is sorted by ASC based on the level column, but check the parent_seq column so that it is sorted under the parent data. And if there are multiple data of the same level, sort by ASC based on the sort column value.
Thanks in advance!
++
EmbraceNothingButFuture's answer was great, but the query seems to work on MySQL 8. I'm using MySQL 5.7. Is there any way to use the query on MySQL 5.7?
Summary:
Use REGEXP_SUBSTR(name,"[0-9]+\-?[0-9]*") to extract the numbers and sort the datas using the numbers.
For MySQL v8 above, you can use LEAD() to generate the "next_level" column based on the "level" column
COALESCE() function for the last default value = 1
SELECT
t1.*,
COALESCE(LEAD(t1.level, 1) OVER(ORDER BY REGEXP_SUBSTR(name,"[0-9]+\-?[0-9]*")), 1) AS next_level
FROM TableA t1
ORDER BY REGEXP_SUBSTR(name,"[0-9]+\-?[0-9]*"), t1.level
See db<>fiddle
I have a table like this
id Bill No Branches_id
1 1 1
2 2 1
3 3 1
4 1 2
5 4 1
when user deletes bill no 2 all other record's bill_no update in numerical order like this
id Bill No Branches_id
1 1 1
3 2 1
4 1 2
5 3 1
is there any easy way to reorder all records without a loop in programmatically
It appears that id is the primary key and you want to update another column within each bill. This can be reasonable.
You can use variables:
declare #rn := 0;
update likethis lt
set bill_no = (#rn := #rn + 1)
where lt.branches_id = 1
order by lt.id;
Note that all foreign references to the table should be using id. If bill_no is used to connect to another table, then you shouldn't change the value (even with cascading foreign keys), unless this is a very rare occurrence.
Suppose I have table called tree with id, and parent-id and data are b-tree
1
2 3
4 5 6 7 8 9
etc
all these are store in tree table like
1 - null
2 - 1
3 - 1
4 - 2
5 - 2
6 - 2
7 - 3
8 - 3
9 - 3
etc
so please write Query to fetch child tree of 2
output should be like
4 - 2
5 - 2
6 - 2
xx - 4
etc..
Select id, parent_id from tablename where parent_id = 2. Perhaps you need bottom level ones? Then you need to left join the table with itself and only return the rows that don't have children.
Edit: if the maximum number of hierarchy levels is high or unknown, you should use hierarchyid: https://msdn.microsoft.com/en-us/library/bb677213.aspx
Hope this helps!
Let's say I have in a table named threadloc:
id thread
4 1
3 2
2 3
1 4
for a table
I want to change the table value of thread so that I can pick any thread and put in on the bottom (id 1) and push all the other threads up one.
So like I pick 2 it would be:
id thread
4 1
3 3
2 4
1 2
UPDATE threadloc SET ID = ID + 1 WHERE thread <> #currentThread AND ID < #currentID;
UPDATE threadloc SET ID = 1 WHERE thread = #currentThread
edit: now it doesn't change higher IDs
I have the table below
relID value charge
1 2 5
1 8 2
2 1 10
2 4 6
2 9 2
For the above table i need for a given value ex 10 to find what to charge for each relID
In the above for value<10 i need to get charge=5 for relID=1 and charge=2 for relID=2
I am trying to use 1 sql command to get it and i am kind of lost
Can anyony help
Thanks
Your question isn't very clear but I think this will work for you
SELECT t.relID,
(
SELECT charge
FROM table
WHERE relID = t.relID
AND value < 10
ORDER BY value
LIMIT 1
) AS charge
FROM table AS t
Let me rephrase.
Here is the table
relID value charge
1 2 5
1 8 2
2 1 10
2 4 6
2 9 2
Explain the table :
Lets say that the value and charge are money.
If the user has value 2 then i must charge with 5 using relID 1
If the user has value 8 then i must charge with 2 using relID 1
same for the relID 2
So when a user come with a value 10 i must find what to charge.So for the given value 10 i must find in the table all records with value<10.
In the example the values for value <10 are
For relID=1 are (2,8)
For relID=2 are (1,4,9)
Now for each relID i need to get the max value.
For relID=1 max value is 8 so charge is 2
For relID=2 max value is 9 so charge is 2
I plain english there are value rate
0-2 charge 5
2-8 charge 2
and ...
i hope to be clear now
select *
from Table t
where value =
(select max(value)
from Table
where value <= 10
and relId = t.relId)