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

落爺英雄遲暮 提交于 2019-12-11 07:12:28

问题


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.


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/15995651/get-n-number-of-records-from-child-table-for-each-parent-record-in-a-mysql-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!