2

我正在使用 php [处理学生考勤系统] 进行我的项目。我有一个学生列表以及他们的唯一 ID [ jntuno],我需要在 mysql 中创建一个数据库,用于存储每个学生在每个科目中的每日出勤率。所以我以这种方式创建了我的表:

students在 mysql 中有一个表,其中包含以下字段和数据:

我的表格内容

现在我想创建一个新表,将jntuno字段中的每个值作为我的新表的列。

我希望我的新表 [让我们命名它attendance] 有这样的列:

+------------+-----------+----------+-----------+-----------+
|11341A0501  |11341A0502 |11341A0503|11341A0504 |11341A0505 |......      
+------------+-----------+----------+-----------+-----------+
|            |           |          |           |           |

如何在 mysql 中执行此操作?

稍后我将向attendance表中添加 3 个字段,即:

-> date[教授特定科目的日期] ,

-> subject[所教科目的名称] 和

-> hours taught[教授特定科目的小时数(可以是 1 或 2 或 3 ... 最多 6)]

每个subject教授特定的date内容都会rowattendance表格中添加一个新内容

例子:

+------------+-----------+-----------------+------------+-----------+----------+-----------+-----------+
|date        |subject    | classes taught  |11341A0501  |11341A0502 |11341A0503|11341A0504 |11341A0505 |..    
+------------+-----------+-----------------+------------+-----------+----------+-----------+-----------+
|2013-09-31  |OOPS       |3                |2           |3          |0         |1          |3          |

我这样选表是为了让考勤进入表的速度更快。

但许多人称这是一个糟糕的数据库结构。所以如果我的问题还有其他好的和有效的数据库设计,请建议我

4

8 回答 8

3

此过程将完成工作:

DELIMITER ||
DROP PROCEDURE IF EXISTS `test`.`pivot`;
CREATE PROCEDURE `test`.`pivot`()
    MODIFIES SQL DATA
BEGIN
    DROP TABLE IF EXISTS `test`.`new_table`;
    SELECT GROUP_CONCAT(CONCAT(`jntunno`, ' CHAR(10) NOT NULL') SEPARATOR ', ') FROM `test`.`students` INTO @sql;
    SET @sql := CONCAT('CREATE TABLE `test`.`new_table` (', @sql, ') ENGINE=InnoDB;');
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    SET @sql := NULL;
END;
||
DELIMITER ;

如果您不能使用存储过程,您可以轻松地将该代码翻译成 PHP 或您使用的任何语言。

于 2013-10-18T09:59:16.453 回答
3

使用以下语句创建新表:

select @s:=concat('create table students_col (',group_concat(jntunno,' CHAR(10)' order by slno),')') from students;
prepare stmt from @s;
execute stmt;
deallocate prepare stmt;

观察如何CREATE TABLE使用group_concat

演示:SQL 小提琴

如果您还想插入名称,这是它的语句:

select @s:=concat('insert into students_col values (',group_concat(concat('"',name,'"') order by slno),')') from students;
prepare stmt from @s;
execute stmt;
deallocate prepare stmt;
select * from students_col;

这是我的整个足迹:

mysql> drop table if exists students;
Query OK, 0 rows affected (0.00 sec)

mysql> create table students (slno integer, jntunno char(10), name varchar(50));
Query OK, 0 rows affected (0.07 sec)

mysql> insert into students values (1,'1134A0501','ADARI GOPI');
Query OK, 1 row affected (0.00 sec)

mysql> insert into students values (2,'1134A0502','BALU');
Query OK, 1 row affected (0.00 sec)

mysql> insert into students values (3,'1134A0503','GEETHA');
Query OK, 1 row affected (0.00 sec)

mysql> drop table if exists students_col;
Query OK, 0 rows affected (0.00 sec)

mysql> select @s:=concat('create table students_col (',group_concat(jntunno,' CHAR(10)' order by slno),')') from students;
+-----------------------------------------------------------------------------------------------+
| @s:=concat('create table students_col (',group_concat(jntunno,' CHAR(10)' order by slno),')') |
+-----------------------------------------------------------------------------------------------+
| create table students_col (1134A0501 CHAR(10),1134A0502 CHAR(10),1134A0503 CHAR(10))          |
+-----------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> prepare stmt from @s;
Query OK, 0 rows affected (0.00 sec)
Statement prepared

mysql> execute stmt;
Query OK, 0 rows affected (0.21 sec)

mysql> deallocate prepare stmt;
Query OK, 0 rows affected (0.01 sec)

mysql> 
mysql> select @s:=concat('insert into students_col values (',group_concat(concat('"',name,'"') order by slno),')') from students;
+------------------------------------------------------------------------------------------------------+
| @s:=concat('insert into students_col values (',group_concat(concat('"',name,'"') order by slno),')') |
+------------------------------------------------------------------------------------------------------+
| insert into students_col values ("ADARI GOPI","BALU","GEETHA")                                       |
+------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> prepare stmt from @s;
Query OK, 0 rows affected (0.00 sec)
Statement prepared

mysql> execute stmt;
Query OK, 1 row affected (0.00 sec)

mysql> deallocate prepare stmt;
Query OK, 0 rows affected (0.00 sec)

mysql> 
mysql> select * from students_col;
+------------+-----------+-----------+
| 1134A0501  | 1134A0502 | 1134A0503 |
+------------+-----------+-----------+
| ADARI GOPI | BALU      | GEETHA    |
+------------+-----------+-----------+
1 row in set (0.00 sec)

mysql> 
于 2013-10-19T07:14:56.320 回答
0
create table new_table
select distinct jntuno from students;

或者

create table new_table (jntuno varchar(10));
insert into new_table 
select distinct jntuno from students;
于 2013-10-06T08:39:15.943 回答
0

尝试

create table new_table (jntuno varchar(10),fieldsname varchar(10));
insert into new_table(jntuno,fieldsname)
values(select distinct jntuno from s tudents,'test');
于 2013-10-06T08:45:06.883 回答
0

我将尝试回答您关于如何更好地设计此数据库的问题:

说明:而不是为每个学生设置一列,我假设每天都有一行,您应该将表设置为每天为每个学生 x 设置一行,并且您可以使用外键来强制数据完整性

造成这种情况的主要原因通常是学生人数不是静态数字。为了在这样的设置中优化您的数据使用,您基本上需要在每次添加或删除学生时重新创建表。因此,如果您从 30 名学生开始,那么您将拥有一个包含 30 列的表,如果每次添加记录时学生人数下降到 15,您将创建 15 个未使用的值,这将逐渐占用比您更多的存储空间实际需要。

解决方案:如果您像这样构建考勤表:

attendance ID | JNTUNO | Date | Subject | Hours

出勤 id 将只是该行的唯一标识符,我建议使用 guid 或自动递增的 int

JNTUNO 将是一个外键,指向您的学生表

这样,在我之前介绍的场景中,有 30 名学生,您每天将添加 30 行,每行有 5 个值,但是当您的学生人数变为 15 时,您只添加 15 行。

我不太了解 MYSQL 语法,但如果我的解释不清楚,如果您愿意,我可以尝试拼凑一个具体的实现;让我知道。

于 2013-10-21T23:15:11.113 回答
0
declare @s as varchar(8000);
declare @s2 as varchar(25);
 set @s ='create table attendance (';
 declare s1  cursor
 for 
 select jntunno from students  
 OPEN s1 
    fetch next from s1 into @s2 
    set @s = @s +'['+@s2 +'] numeric(4,2)'
    fetch next from s1 into @s2
     WHILE @@FETCH_STATUS = 0
     BEGIN
         set @s = @s +',['+@s2 +'] numeric(4,2)'
         fetch next from s1 into @s2
     end
 CLOSE s1 -- close the cursor
DEALLOCATE s1
set @s = @s+')'
exec(@s)
于 2013-10-23T07:38:15.543 回答
0

您不希望每次添加学生时都添加列。

我会这样设计它:

Table:  Attendance
    Columns:
        Date
        Subject
        ClassNumber
        Missed_jntuno

然后,为每个错过的学生/班级组合添加一行(或者,如果学生错过的次数超过他们参加的次数,您可能希望将其翻转到一个Attended_jntuno字段,并在他们进入课堂时添加该行 - 或者如果您真的感觉很完整,总是为每个学生写一行,然后有另一个位/布尔列用于出席与否)。

这种方式的一个优点是,除了每日总和之外,您还可以查看哪些班级获得了哪些学生。另一个是这对于灵活报告的 OLAP 多维数据集之类的东西要友好得多。

于 2013-10-24T10:27:53.770 回答
0

基本的数据库设计现在正在跳起来,当着你的面大喊:“你做错了!”。

您在这里尝试做的是在 1 个表中放置多对多关系,而实际上应该在 3 个表中。

你应该做的是保持你的学生表原样,并subjects为每个主题添加一个包含 1 行的表,但不包括日期。

然后,您想要另一个表Attendance,其中包含学生 ID 的参考列、主题 ID 的参考列、日期字段和状态字段。

您现在要做的是尝试在有关表的元数据中存储基本上易失的数据,这是您永远不应该做的。例如,如果您有一个学生在入学 1 周后加入您的学校怎么办?然后你的表突然多了一个第一周没有值的列。

此外,您的系统意味着数据库查询要困难得多,因为您将要过滤的数据存储在列标题中。这里的其他人给出了许多理由说明这是一个坏主意。

于 2013-10-25T07:35:06.733 回答