2011-04-29 21 views
6

को देखते हुए निम्न तालिकाओं में 'चपटा' होने की जरूरत है:दो तालिकाओं में शामिल हों (एक 1 एम रिश्ते के साथ) जहां दूसरी तालिका एक पंक्ति

छात्र

+----+-------+ 
| id | Name | 
+----+-------+ 
| 1 | Chris | 
| 2 | Joe | 
| 3 | Jack | 
+----+-------+ 

नामांकन

+---------------+------------+-----------+----------+ 
| enrollment_id | student_id | course_id | complete | 
+---------------+------------+-----------+----------+ 
| 1    | 1   | 55  | true  | 
| 2    | 1   | 66  | true  | 
| 3    | 1   | 77  | true  | 
| 4    | 2   | 55  | true  | 
| 5    | 2   | 66  | false | 
| 6    | 3   | 55  | false | 
| 7    | 3   | 66  | true  | 
+---------------+------------+-----------+----------+ 

मुझे निम्नलिखित

+----+-------+-----------+-----------+-----------+ 
| id | Name | Course 55 | Course 66 | Course 77 | 
+----+-------+-----------+-----------+-----------+ 
| 1 | Chris | true  | true  | true  | 
| 2 | Joe | true  | false  | NULL  | 
| 3 | Jack | false  | true  | NULL  | 
+----+-------+-----------+-----------+-----------+ 

नोट 1: मैं जानता हूँ कि mysql गतिशील कॉलम (मुझे ठीक कर लें मैं गलत हूँ!) तो मैं प्रश्न के रूप में शुरू करने के साथ खुश हूँ नहीं कर सकते हैं:

SELECT id, name, course_55, course_66, course_77 etc... 

मैं इस के साथ खुश है क्योंकि वहाँ एक पाठ्यक्रमों की निश्चित संख्या (4 सटीक होना)। आदर्श रूप से मैं इसे गतिशील होना चाहता हूं; यानी, चयन खंड में प्रत्येक पाठ्यक्रम मैन्युअल रूप से लिखना नहीं है।

नोट 2: यह mysql शुद्ध की आवश्यकता है - मैं PHP का सहारा लेना नहीं चाहता हूं।

वर्तमान में डेटाबेस 10000+ * 4 नामांकन के साथ 10000+ छात्रों पर खड़ा है (क्योंकि बिल्कुल 4 पाठ्यक्रम हैं, और प्रत्येक छात्र सभी 4 मॉड्यूल में है)।

नोट 3: Student.user_id अनुक्रमित है और इसलिए नामांकन .enrollment_id, nomment.student_id, और nomment.course_id है।

उत्तर

9
select s.id,s.name, 
max(case when e.course_id = 55 then complete else null end) as c55, 
max(case when e.course_id = 66 then complete else null end) as c66, 
max(case when e.course_id = 77 then complete else null end) as c77 
from student as s 
left join enrollment as e 
on s.id = e.student_id 
group by s.id 

@ क्रिस। संग्रहीत प्रक्रिया का उपयोग करके आप स्तंभों की संख्या से पहले बिना ज्ञात गतिशील पिवट तालिका भी बना सकते हैं। यह एक इतालवी मंच पर लिंक

http://forum.html.it/forum/showthread.php?s=&threadid=1456236

एक ऐसी ही समस्या के लिए मेरा एक जवाब की है। एक पूरा उदाहरण है जो आपको तर्क के पीछे समझने में मदद कर सकता है। :)

संपादित करें। ने MySQL गतिशील दृश्य के साथ अद्यतन

यह मेरा प्रारंभ डंप है:

/*Table structure for table `student` */ 

drop table if exists `student`; 

create table `student` (
    `id` int(10) unsigned not null auto_increment, 
    `name` varchar(50) default null, 
    primary key (`id`) 
) engine=myisam; 

/*Data for the table `student` */ 

insert into `student`(`id`,`name`) values (1,'chris'); 
insert into `student`(`id`,`name`) values (2,'joe'); 
insert into `student`(`id`,`name`) values (3,'jack'); 

drop table if exists enrollment; 

create table `enrollment` (
    `enrollment_id` int(11) auto_increment primary key, 
    `student_id` int(11) default null, 
    `course_id` int(11) default null, 
    `complete` varchar(50) default null 
) engine=myisam auto_increment=8 default charset=latin1; 

/*Data for the table `enrollment` */ 

insert into `enrollment`(`enrollment_id`,`student_id`,`course_id`,`complete`) values (1,1,55,'true'); 
insert into `enrollment`(`enrollment_id`,`student_id`,`course_id`,`complete`) values (2,1,66,'true'); 
insert into `enrollment`(`enrollment_id`,`student_id`,`course_id`,`complete`) values (3,1,77,'true'); 
insert into `enrollment`(`enrollment_id`,`student_id`,`course_id`,`complete`) values (4,2,55,'true'); 
insert into `enrollment`(`enrollment_id`,`student_id`,`course_id`,`complete`) values (5,2,66,'false'); 
insert into `enrollment`(`enrollment_id`,`student_id`,`course_id`,`complete`) values (6,3,55,'false'); 
insert into `enrollment`(`enrollment_id`,`student_id`,`course_id`,`complete`) values (7,3,66,'true'); 

और इस गतिशील दृश्य के लिए भंडारित किया प्रक्रिया है:

delimiter // 
drop procedure if exists dynamic_view// 
create procedure dynamic_view() 
begin 
declare finish int default 0; 
declare cid int; 
declare str varchar(10000) default "select s.id,s.name,"; 
declare curs cursor for select course_id from enrollment group by course_id; 
declare continue handler for not found set finish = 1; 
open curs; 
my_loop:loop 
fetch curs into cid; 
if finish = 1 then 
leave my_loop; 
end if; 
set str = concat(str, "max(case when e.course_id = ",cid," then complete else null end) as course_",cid,","); 
end loop; 
close curs; 
set str = substr(str,1,char_length(str)-1); 
set @str = concat(str," from student as s 
      left join enrollment as e 
      on s.id = e.student_id 
      group by s.id"); 
prepare stmt from @str; 
execute stmt; 
deallocate prepare stmt; 
-- select str; 
end;// 
delimiter ; 

अब यह

mysql> call dynamic_view(); 
+----+-------+-----------+-----------+-----------+ 
| id | name | course_55 | course_66 | course_77 | 
+----+-------+-----------+-----------+-----------+ 
| 1 | chris | true  | true  | true  | 
| 2 | joe | true  | false  | NULL  | 
| 3 | jack | false  | true  | NULL  | 
+----+-------+-----------+-----------+-----------+ 
3 rows in set (0.00 sec) 

Query OK, 0 rows affected (0.05 sec) 
कॉल

अब हम दो अलग-अलग पाठ्यक्रमों के साथ अन्य दो रिकॉर्ड डालते हैं:

insert into `enrollment`(`student_id`,`course_id`,`complete`) values (1,88,'true'); 
insert into `enrollment`(`student_id`,`course_id`,`complete`) values (3,99,'true'); 

और हम प्रक्रिया को याद करते हैं। यह परिणाम है:

mysql> call dynamic_view(); 
+----+-------+-----------+-----------+-----------+-----------+-----------+ 
| id | name | course_55 | course_66 | course_77 | course_88 | course_99 | 
+----+-------+-----------+-----------+-----------+-----------+-----------+ 
| 1 | chris | true  | true  | true  | true  | NULL  | 
| 2 | joe | true  | false  | NULL  | NULL  | NULL  | 
| 3 | jack | false  | true  | NULL  | NULL  | true  | 
+----+-------+-----------+-----------+-----------+-----------+-----------+ 
3 rows in set (0.00 sec) 

Query OK, 0 rows affected (0.02 sec) 

यह सब कुछ है।:)

+0

@nick यह शानदार है, मुझे खंड के मामले में अवगत नहीं था। हालांकि यह बहुत अच्छा काम करता है, मैं सप्ताहांत में इसके बारे में पढ़ूंगा (मुझे हमेशा कोड में प्लग करने की बजाय कुछ समझना पसंद है)। गतिशील पिवट तालिका वास्तव में भी दिलचस्प है, मैं इसका अनुवाद करूंगा, और इसे पढ़ने के लिए प्रयास करूंगा। इस तरह के सुरुचिपूर्ण के रूप में एक जवाब ठीक है क्यों SO बहुत उपयोगी है। – Chris

+0

हाय क्रिस। जैसे ही मैं कर सकता हूं, मैं अपने उदाहरण के आधार पर एक गतिशील संस्करण के साथ अपना उत्तर अपडेट करूँगा :) –

+0

हाय निक, अगर आप कर सकते हैं तो यह बहुत अच्छा होगा, लेकिन यदि आपके पास समय नहीं है, तो यह भी ठीक है। धन्यवाद फिर से – Chris