MySQL Select query to fetch record base on list values

后端 未结 2 1862
面向向阳花
面向向阳花 2021-01-22 12:17

I am using MySQL. I have 3 Table as below.

Table : subject_Master

--------------------------
subjectId   | subjectShortName
----------------------------         


        
相关标签:
2条回答
  • 2021-01-22 12:34

    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
    0 讨论(0)
  • 2021-01-22 12:40

    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;
    
    0 讨论(0)
提交回复
热议问题