问题
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