Get N number of records from child table for each parent record in a MySQL View

StackOverflow https://stackoverflow.com/questions/15995651

  •  03-04-2022
  •  | 
  •  

سؤال

I tried finding answer to this question in SO , but could not find any. Any links will be of great help.

I have a parent table and a child table with one to many relationship between the parent and child table. The child table contains around 1 million records and I want to create a view with 1st 10 records in child table for each parent record. Example-

Parent_Table - Fields -- ID, Name
ID       Name
----     -----
1        A
2        B
3        C

Child_Table - Fields -- ID, ParentID, Date, Data
ID  ParentID  Date    Data
--------------------------
1     1        04/10   A1
2     1        04/11   A2
3     1        04/11   A3
4     1        04/12   A4
5     1        04/12   A5
6     2        04/10   B1
7     2        04/11   B2
8     2        04/12   B3
9     2        04/12   B4
10    2        04/13   B5
11    2        04/13   B6

Now, I want to create a view with 1st 4 records for each parent record sorted by date.

Output Expected

ID  ParentID  Date    Data
--------------------------
1     1        04/10   A1
2     1        04/11   A2
3     1        04/11   A3
4     1        04/12   A4
6     2        04/10   B1
7     2        04/11   B2
8     2        04/12   B3
9     2        04/12   B4

Any links or guide to the solution will be appreciated. Thanks in advance!

In case you need any clarification, please post a comment.

هل كانت مفيدة؟

المحلول

If you need to create a VIEW, you could use something like this:

CREATE VIEW First_Four AS
SELECT c1.*
FROM
  Child_Table c1 LEFT JOIN Child_Table c2
  ON c1.ParentID = c2.ParentID
     AND (STR_TO_DATE(c1.`date`, '%m/%Y')>STR_TO_DATE(c2.`date`, '%m/%Y')
          OR (STR_TO_DATE(c1.`date`, '%m/%Y')=STR_TO_DATE(c2.`date`, '%m/%Y')
              AND c1.ID>c2.ID)
         ) 
GROUP BY
  c1.ID, c1.ParentID, c1.`Date`, c1.Data
HAVING
  COUNT(c2.ID)<4

I'm considering the field data as a VARCHAR column, so we need to use STR_TO_DATE, if it is not we can just compare c1.date with c2.date directly.

Please see fiddle here.

نصائح أخرى

I tried this one my computer and it displayed based on your requirements using your own data. I changed some field name though like ID of Child to ChildID, Date to ChildDate, Data to ChildData. Here it is:

SELECT * FROM 
(SELECT ParentID, ChildID, ChildDate, ChildData, @ChildRank:= CASE WHEN @Parent <> ParentID THEN 1 ELSE @ChildRank+1 END as ChildRanking, @Parent := ParentID as Parent FROM 
(SELECT @ChildRank:=0) CR, (SELECT @Parent:=1) P, (SELECT * FROM Child_Table ORDER BY
ParentID, ChildID) MainTable) AllTable WHERE ChildRanking <=4;

I use only the Child Table only but anyway you could INNER JOIN this with Parent_Table if you like.

A little explanation:

1) ChildRank will starts with Rank 0 (i.e. SELECT @ChildRank:0) but because of @ChildRank+1 it will start with Rank 1

2) When new ParentID (i.e. @Parent<> ParentID) then starts with Rank 1 right away.

3) AllTable is the alias for everything so that you could now reference the ChildRanking field.

If you don't want to display the ChildRanking field then you have to specify the fields you want to dispaly.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top