4 JOIN에서 1개의 테이블을 피벗해야 합니다.
이것은 매우 구체적인 문제입니다. 제가 거기서 무엇을 하고 싶은지 이해해주셨으면 합니다.
(MariaDB)
내 테이블:
table_to teach:
티치아이드 | 가르치다 | 선생님. | .... | .... |
---|---|---|---|---|
1.0 | 서브j1- | Tname1 | ||
1.2 | 서브j2- | Tname1 |
table_message:
학생입니다 | ... | ... |
---|---|---|
stname1 | -- | -- |
stname2 | -- | -- |
stname3 | -- | -- |
stname4 | -- | -- |
(x-stname의 양) | -- | -- |
table_stpresents:
이것은 출석 기록이며 각 학생과 각 요일마다 한 줄씩 있습니다.학생이 하루 시작에 참석하는 경우, 학생은 해당 날짜에 예약된 각 수업에 참석한 것으로 예상됩니다.
학생입니다 | 날짜. | 현재의. |
---|---|---|
stname1 | 날짜 1 | 네 - |
stname2 | 날짜 1 | 아니 - |
x개의 stname 양 | 날짜 1 | -네 - |
stname1 | 날짜 2 | -아니- |
stname2 | 날짜 2 | -네 - |
x개의 stname 양 | 날짜 2 | -네 - |
table_message:
학생 이름은 여기서 CSV(쉼표로 구분된 문자열) 값으로 참조되며, 매일 각 시간 테이블 클래스에 대해 행이 하나씩 있습니다.
날짜. | 서브j1 | 서브j2 | 서브j3 | stnames |
---|---|---|---|---|
날짜 1 | 서브j1- | 서브j3- | 서브j2- | stname1, stname2, stname5 |
날짜 X | 서브j3- | 서브j2- | 서브j1- | stname1, stname4, stname3, stname5 |
예상 결과:
한 의 열이 ▁the▁for▁that▁for▁show▁row▁1▁has▁contains다▁that▁subject▁column▁and니▁one시표합▁each각을행나▁student하의▁each해대목과에가 포함된 행을 보여줍니다.LDUS
학생이 참석한 날짜와 해당 학생에 해당하는 시간표 기록을 기준으로 해당 학생에게 과목이 강의된 최신 날짜.
테이블 열 개수는 다른 제목 그룹을 선택하여 변경됩니다(이 테이블은 사용자 지정 UI의 일부가 됨).
참고: 내 코드는 동적으로 SQL 코드를 생성할 수 있으므로 동적 SQL 솔루션이 필요하지 않습니다.
티치아이드 | 가르치다 | 선생님. | stname1 | stname2 | ..... | stnameX |
---|---|---|---|---|---|---|
1.0 | 서브j1- | Tname1 | -LDUS- | -LDUS- | -LDUS- | |
1.2 | 서브j2- | Tname2 | -LDUS- | -LDUS- | -LDUS- |
갱신하다
저는 몇 가지 예제 데이터를 준비했습니다. https://dbfiddle.uk/ ?rdbms=sysadb_10.3&sysdle=4bf254 2240eaa86e4f4624c1e376215a.
첫 번째 작업은 이 모든 테이블을 올바르게 결합하고 데이터를 정규화하는 것입니다.그런 다음 원본 데이터가 올바른지 확인한 후 행을 피벗하는 방법을 물어볼 수 있습니다.
소스 데이터는 두 가지 구조적 문제로 인해 복잡합니다.
- 의
table_timetable
테이블이 여러 열에 걸쳐 나열됩니다.이 데이터를 정규화하기 위해 각 주제 열에 대해 표를 한 번씩 쿼리하고 결과를 함께 결합할 수 있습니다.- 의 학생들
table_timetable
테이블은 CSV 문자열 값으로 저장됩니다. MariaDB에는 이러한 유형의 데이터를 쿼리하는 내장 함수가 없지만 CTE를 사용하여 이름을 개별 행으로 분할할 수 있습니다. 이 내용은 이 SO 질문에서 설명합니다. SQL(Maria DB) 분할 문자열을 쉼표로 구분하여 행으로 구분합니다.
집에 있는 모든 사람들에게, 이 두 가지 합병증 없이 비슷한 요구사항이 있다면, 이 단순화된 피들은 도움이 될 것입니다: https://dbfiddle.uk/ ?rdbms=sysadb_10.3&nbdle=9dfce7084321699d1262bbb50ca724d9e.
다음 쿼리는 레코드 집합을 정규화합니다.
with recursive cte as (
select `Date`,subj1,subj2,subj3,' ' as stname, concat(stnames, ',') as stnames, 1 as lev
from table_timetable
union all
select `Date`,subj1,subj2,subj3,substring_index(stnames, ',', 1),
substr(stnames, instr(stnames, ',') + 2), lev + 1
from cte
where stnames like '%,%'
)
, bySubject as (
select `Date`,subj1 as subj, stname
from cte
where lev > 1
union all
select `Date`,subj2 as subj, stname
from cte
where lev > 1
union all
select `Date`,subj3 as subj, stname
from cte
where lev > 1
)
select `Date`,subj,stname
from bySubject
테스트 DB의 경우 다음과 같습니다.
|날짜 |subj |stname ||--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|stname1| ...
여기에서 피들을 참조하십시오. https://dbfiddle.uk/ ?rdbms=sysadb_10.3&fsdle=f31cab287fdd575054e3af457a9cf14d
마지막으로 이 데이터를 각 학생의 열로 피벗합니다.여기서 MariaDB는 실제로 우리를 실망시키고, 피벗에 대한 내장된 지원이 없으며, 사용자가 직접 결과를 수동으로 구성해야 합니다.더 많은 CTE를 사용할 수 있지만, 애플리케이션이 SQL을 구성할 수 있다면, 더 간단한 쿼리는 단순히CASE
각 열을 구성하는 문:
with recursive cte as (
select `Date`,subj1,subj2,subj3,' ' as stname, concat(stnames, ',') as stnames, 1 as lev
from table_timetable
union all
select `Date`,subj1,subj2,subj3,substring_index(stnames, ',', 1),
substr(stnames, instr(stnames, ',') + 2), lev + 1
from cte
where stnames like '%,%'
)
, bySubject as (
select `Date`,subj1 as subj, stname
from cte
where lev > 1
union all
select `Date`,subj2 as subj, stname
from cte
where lev > 1
union all
select `Date`,subj3 as subj, stname
from cte
where lev > 1
)
select teacher.`teach-id`, teach, teacher
, MAX(CASE WHEN stname = 'stname1' THEN attendance.Date END) AS stname1
, MAX(CASE WHEN stname = 'stname2' THEN attendance.Date END) AS stname2
, MAX(CASE WHEN stname = 'stname3' THEN attendance.Date END) AS stname3
, MAX(CASE WHEN stname = 'stname4' THEN attendance.Date END) AS stname4
, MAX(CASE WHEN stname = 'stname5' THEN attendance.Date END) AS stname5
FROM bySubject tt
/*INNER JOIN table_students s ON tt.stname = s.student*/
INNER JOIN table_stpresents attendance ON tt.Date = attendance.Date AND tt.stname = attendance.student
INNER JOIN table_toteach teacher ON tt.subj = teacher.teach
WHERE attendance.present = '- yes -'
GROUP BY teacher.`teach-id`, teach, teacher
ORDER BY `teach-id`;
참고: 가입에 대해 의견을 제시했습니다.
table_student
해당 테이블의 정보가 필요하지 않기 때문에 실제로 이 출력에 정보를 포함하는 것은 어려울 수 있습니다. 열 이름을 해결해야 할 경우 응용 프로그램 논리에 맡기는 것이 좋습니다.
조인을 사용하여 필터 기준을 추가할 수 있으므로 탐색할 수 있도록 남겨 둡니다.
그 결과:
티치아이드 | 가르치다 | 선생님. | stname1 | stname2 | stname3 | stname4 | stname5 |
---|---|---|---|---|---|---|---|
1.0 | 서브j1- | Tname1 | 2021-08-18 | 2021-08-18 | 2021-08-19 | 2021-08-19 | 2021-08-18 |
1.2 | 서브j2- | Tname2 | 2021-08-18 | 2021-08-18 | 2021-08-19 | 2021-08-19 | 2021-08-18 |
1.5 | 서브j3- | Tname3 | 2021-08-18 | 2021-08-18 | 2021-08-16 | 2021-08-19 | 2021-08-18 |
2.0 | 서브j4- | Tname4 | 2021-08-18 | 2021-08-18 | 2021-08-19 | 2021-08-18 |
은 이은더간형다니태입의 더 간단한 입니다.PIVOT
코드에서 쿼리를 생성하는 경우 유지 관리하려면 각 학생 열에 대해 max 문을 반복하면 됩니다.
이 최종 솔루션은 다음 db<>dbms https://dbfiddle.uk/ ?rdbms=sysadb_10.3&dbdle=f07c943d3d92ea0de8d91021728ab7c0에 있습니다.
다른 방법은 피벗 인 마리아(Pivoting in MariaDB
언급URL : https://stackoverflow.com/questions/68831109/need-to-pivot-1-table-in-4-joins
'programing' 카테고리의 다른 글
MariaDB 가져오기 최대 키 길이 (0) | 2023.06.09 |
---|---|
변수를 십진수로 선언 (0) | 2023.06.09 |
열 레이블을 변경하시겠습니까? 예: 열 "A"를 열 "이름"으로 변경합니다. (0) | 2023.06.09 |
IPython을 사용한 단계별 디버깅 (0) | 2023.06.09 |
여러 스레드가 동일한 메모리에 액세스하지 않도록 하여 잠금을 방지할 수 있습니까? (0) | 2023.06.09 |