Parent-child table
id
introducer_id
name
1
NULL
Riya
2
1
Ramesh
3
1
Anand
4
2
Preety
5
3
Rakesh
Query to get members list when id = 1
select id AS memberid, name
from (select *
from table_member
order by introducer_id, id) table_member_sorted,
(select #pv := '1') initialisation
where find_in_set(introducer_id, #pv)
and length(#pv := concat(#pv, ',', id))
The above query displays output
member_id
name
2
Ramesh
3
Anand
4
Preety
5
Rakesh
Now i also want to find the level of all the members
(i.e) i want the output as:
member_id
name
level
2
Ramesh
1
3
Anand
1
4
Preety
2
5
Rakesh
2
How can i update my previous query to get the above output?
Note: Query to display maximum level upto 7
Thank You.
CREATE PROCEDURE get_tree (start_from INT)
BEGIN
DROP TABLE IF EXISTS tmp;
CREATE TABLE tmp (member_id INT PRIMARY KEY,
name VARCHAR(255),
level INT);
INSERT INTO tmp SELECT id, name, 0
FROM test
WHERE id = start_from;
REPEAT
INSERT IGNORE INTO tmp SELECT test.id, test.name, tmp.level + 1
FROM test
JOIN tmp ON tmp.member_id = test.introducer_id;
UNTIL !ROW_COUNT() END REPEAT;
SELECT * FROM tmp;
END
fiddle
I have shared screenshot link of my sql version. snipboard.io/qbdB0A.jpg – AfreenB
Your SQL server version is MariaDB 10.4.14. – Akina
For your server version use
WITH RECURSIVE
cte AS ( SELECT id member_id, name, 0 level
FROM test
WHERE id = #start_from
UNION ALL
SELECT test.id, test.name, cte.level + 1
FROM test
JOIN cte ON cte.member_id = test.introducer_id
-- WHERE cte.level < 7 )
SELECT *
FROM cte;
fiddle
Related
I have a MySQL table with following data:
ID Name ParentID
1 Foo null
2 Bar null
3 Foo SubA 1
4 Bar SubA 2
5 Foo SubC 1
6 Foo SubB 1
I would like to retreive all data with following order:
1 Foo null
3 Foo SubA 1
6 Foo SubB 1
5 Foo SubC 1
2 Bar null
4 Bar SubA 2
Is it possible with MySQL and single query?
If this is a two-level hierarchie, i.e. no grandparents and grandchildren, it's a mere ORDER BY clause:
select id, name, parentid
from mytable
order by coalesce(parentid, id), parentid is not null, name;
This makes use of MySQL's true = 1, false = 0. parentid is not null is 0 for the parent and 1 for the children.
You could use recursive CTE (MySQL 8.0+):
-- 2 level hierarchy (parent-child)
WITH RECURSIVE cte AS
(
SELECT tx.*, 1 AS lvl, ID AS grp FROM tx WHERE ParentID IS NULL
UNION ALL
SELECT tx.*, lvl+1, cte.ID FROM tx JOIN cte WHERE tx.ParentId = cte.Id
)
SELECT ID, Name, ParentId
FROM cte
ORDER BY grp, lvl, Name;
DBFiddle Demo
I need your help. I have a table named Test_Result with 2 columns as shown below.
ID Source_ID
10 1
20 2
30 2
40 3
50 3
60 3
70 4
I am trying to get output as below,but unable to get logic.
ID Parent_ID Source_ID
10 Null 1
20 Null 2
30 20 2
40 Null 3
50 40 3
60 50 3
70 Null 4
Kindly help me with this scenario. I attached question in picture for as well.
Regards,
Abhi
These solutions (ROW_NUMBER/LAG) will work for MySQL 8.0+ or MariaDB 10.2
You could use ROW_NUMBER() and join to previous row:
CREATE TABLE tab(ID INT ,Source_ID INT);
INSERT INTO tab(id, Source_id)
SELECT 10, 1
UNION ALL SELECT 20 , 2
UNION ALL SELECT 30, 2
UNION ALL SELECT 40 , 3
UNION ALL SELECT 50 , 3
UNION ALL SELECT 60 , 3
UNION ALL SELECT 70 , 4;
WITH cte AS (
SELECT *, ROW_NUMBER() OVER(ORDER BY id) AS rn
FROM tab
)
SELECT c1.ID,
CASE WHEN c1.Source_ID = c2.Source_ID THEN c2.Id END AS Parent_Id,
c1.Source_ID
FROM cte c1
LEFT JOIN cte c2
ON c1.rn = c2.rn+1;
Rextester Demo
EDIT:
Using LAG() windowed function:
SELECT c1.ID,
CASE
WHEN c1.Source_ID = LAG(Source_ID) OVER w THEN LAG(ID) OVER w
END AS Parent_Id,
c1.Source_ID
FROM tab c1
WINDOW w AS (ORDER BY ID)
ORDER BY id;
DBFiddle
EDIT2:
Simulating LAG using variables:
SET #lag_Source_id='';
SET #lag_Id = '';
SELECT ID,
CASE WHEN Source_Id = lag_Source_ID THEN lag_ID END AS Parent_ID
,Source_ID
FROM (
SELECT ID
, Source_ID
, #lag_Source_id AS lag_Source_id
, #lag_Source_id:= Source_ID AS curr_Source_ID
, #lag_Id AS lag_ID
, #lag_Id := ID AS curr_ID
FROM tab
ORDER BY id
) AS sub
RextesterDemo2
if you are using mysql database simply do this,
SELECT ID, (ID + Source_ID) AS Parent_ID, Source_ID FROM tableName LIMIT 10;
I have a table department_courses with following structure :
id department_id name
-- ------------- -----
1 11 Abcd
2 11 Bghg
3 11 Lopps
4 13 Abvgf
So from this table I need to count the position of the subquery. I mean to say , The position of the name Lopps for department_id is 3 . How to get this in mysql query?
If you only need to do this for one row, then a single query is simpler:
select count(*)
from department_courses dc
where dc.id <= (select dc2.id
from department_courses dc2
where dc2.name = 'Lopps'
);
If you want to assign a row number to all rows, then variables are probably a better method.
Try:
select row_num
from (
select t.*, #r := #r + 1 row_num
from department_courses t,
(select #r := 0) r
) x
where x.name = 'Lopps'
x.department_id = 3
Until today i thought i know something about MySQL.
OK lets say we have one table like this:
id | some_name |some_number
-----------------------------
1 | test | 33
2 | test | 34
3 | test | 35
3 | test2 | 36
3 | test2 | 37
and i want to write query to return something like this:
test 33
test 34
test2 36
test2 37
test3 12
test3 34
.
.
.
and so on. I want to return only 2 result per same name. It is easy to use limit and return only one result per name but I'm stuck to return multiple results per same name in this case 2 but might be an n results. Work around is to make some script that will do:
select some_name, some_number from tbl_name limit 2;
and to repeat it for every distinct some_name i have in table.
Is there any elegant solution for MySQL? I would be grateful if you share that with me.
You can use a user variable to add a counter of each row of a name, then just select the rows where the counter is less than or equal to 2 (untested):-
SELECT some_name, some_number
FROM
(
SELECT some_name, some_number, #cnt=(#some_name = some_name, #cnt + 1, 1) AS cnt, #some_name:=some_name
FROM
(
SELECT some_name, some_number
FROM tbl_name
ORDER BY some_name, some_number
) sub0
CROSS JOIN
(
SELECT #some_name:='', #cnt:=0
)
sub1
) sub2
WHERE cnt <= 2
you could try this,
select some_name,some_number from yourTable t
where
(select count(*) from yourTable
where
some_number<=t.some_number and some_name=t.some_name)<3
This partially solved my problem:
set #num := 0, #name := '';
select distinct number, name
from (
select number, name,
#num := if(#name = name, #num +1, 1) as row_number,
#name := name as dummy
from karian2
) as x where x.row_number <= 2;
It fails some time to return 2 results because sub query is not returning distinct values. Example here:
http://sqlfiddle.com/#!2/952ca/23
How to create table with a column computed by another table in SQL Server?
For example:
TableA:
Name SerialNoStart SerialNoEnd
A 1 3
B 2 4
C 1 1
I want create a new table with serial number between SerialNoEnd and SerialNoStart
The new table as following:
TableB:
Name SerialNo
A 1
A 2
A 3
B 2
B 3
B 4
C 1
How to make it? Thanks!
You can split the data out using a recursive CTE, similar to this:
;with data(name, SerialNoStart, SerialNoEnd) as
(
select name, SerialNoStart, SerialNoEnd
from TableA
union all
select name, SerialNoStart +1, SerialNoEnd
from data
where SerialNoStart +1 <= SerialNoEnd
)
select name, SerialNoStart as SerialNo
from data
order by name
See SQL Fiddle with Demo