问题
I am using MySQL. I have 3 Table as below.
Table : subject_Master
--------------------------
subjectId | subjectShortName
----------------------------------
1 | English
2 | French
3 | German
4 | Latin
----------------------------------
Table : class_Master
-----------------------------------
classId | className
----------------------------------
1 | Rose
2 | Dasy
3 | Lily
Table : subjectAllocation
------------------------------------------
allocationId | classId | subjectId
-------------------------------------------
1 | 1 | 1,2
2 | 2 | 2,3,4
3 | 3 | 1,2,3,4
How I can get SQL result as following, Want to fetch SubjectName for each subjectId in subjectAllocation row
ClassName | SubjectName
-------------------------------------------
Rose | English,French
Dasy | French,German,Latin
Lily | English,French,German,Latin
回答1:
Use FIND_IN_SET() function:
Try this:
SELECT A.allocationId,
B.className,
GROUP_CONCAT(C.subjectShortName) AS subjectName
FROM subjectAllocation A
INNER JOIN class_Master B ON A.classId = B.classId
INNER JOIN subject_Master C ON FIND_IN_SET(C.subjectId, A.subjectId)
GROUP BY A.allocationId;
回答2:
plan
- fix
subjectAllocation
so it is accessible & linkable- use sequence generator ( from digits_v ) to unroll variable length string into structured data
- access the structured data in simple way, joining on indexed fields
setup
create table subject_Master
(
subjectId integer primary key not null,
subjectShortName varchar(23) not null
);
create table class_Master
(
classId integer primary key not null,
className varchar(23) not null
);
create table subjectAllocation_inaccessible
(
allocationId integer primary key not null,
classId integer not null,
subjectId varchar(32) not null,
foreign key ( classId ) references class_Master ( classId )
);
create table subjectAllocation
(
allocationId integer primary key not null,
classId integer not null,
subjectId integer not null,
foreign key ( classId ) references class_Master ( classId ),
foreign key ( subjectId ) references subject_Master ( subjectId )
);
insert into subject_Master
( subjectId, subjectShortName )
values
( 1 , 'English' ),
( 2 , 'French' ),
( 3 , 'German' ),
( 4 , 'Latin' )
;
insert into class_Master
( classId, className )
values
( 1 , 'Rose' ),
( 2 , 'Dasy' ),
( 3 , 'Lily' )
;
insert into subjectAllocation_inaccessible
( allocationId, classId, subjectId )
values
( 1 , 1 , '1,2' ),
( 2 , 2 , '2,3,4' ),
( 3 , 3 , '1,2,3,4' )
;
fix subjectAllocation
create view digits_v
as
SELECT 0 AS N
UNION ALL
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5
UNION ALL
SELECT 6
UNION ALL
SELECT 7
UNION ALL
SELECT 8
UNION ALL
SELECT 9
;
insert into subjectAllocation
( allocationId, classId, subjectId )
select @row_number := @row_number + 1 as allocationId, sa.classId, substring_index(substring_index(sa.subjectId, ',', n.n), ',', -1) sub
from subjectAllocation_inaccessible sa
cross join
(
select a.N + b.N * 10 + 1 n
from digits_v a
cross join digits_v b
order by n
) n
cross join ( select @row_number := 0 ) params
where n.n <= 1 + (length(sa.subjectId) - length(replace(sa.subjectId, ',', '')))
;
simplicity of access
select c.className, group_concat(s.subjectShortName)
from subjectAllocation sa
inner join class_Master c
on sa.classId = c.classId
inner join subject_Master s
on sa.subjectId = s.subjectId
group by c.className
;
here the join to class_Master can use the primary index ( subjectId )
output
+-----------+----------------------------------+
| className | group_concat(s.subjectShortName) |
+-----------+----------------------------------+
| Dasy | French,German,Latin |
| Lily | German,Latin,English,French |
| Rose | English,French |
+-----------+----------------------------------+
sqlfiddle
reference
- SO mysql sequence generator
- junction tables
- SO How to store arrays in mysql
- database normalisation
来源:https://stackoverflow.com/questions/34553775/mysql-select-query-to-fetch-record-base-on-list-values