我对编程很陌生,但我正在编写一些软件来收集,存储和处理数据。
我有数据显示人们上下班的时间,如图A所示(这是一个SQL CE数据库(Compact Edition,No Pivoting允许),我使用C#和WPF编程)。我希望能够将表A中的数据转换为表B中的表单,其中多个条目按日期分类为单行,将每个人在相应行日期上花费的时间分配给他的列,并将总通勤小时数相加结束。
我确实陷入困境,想知道如何做到这一点。 我已经得到了应用程序来收集和存储这些数据,如表A所示,我想生成表B:
答案 0 :(得分:1)
从您的问题中不清楚您是在尝试在内存中(即在程序中)还是在SQL中创建表。当您要求“将数据转换为表单”时,我知道您正在尝试使用新表单创建SQL表。
您的要求的问题是您要创建一个包含每个人的列的行(记录)。为此,您必须获取每一行,检查该人的列是否已存在,如果不存在,则创建该列(使用ALTER命令)。虽然这是可能的,但这不是使用SQL表的常规方法。
正常的方法是将表A原样保留,并按“staff”(SELECT * FROM tableA ORDER BY date,Staff)排序读取并相应地计算结果。注意 - 您应该在“Staff”列中定义索引。这样做不需要改变表格格式,但需要编写程序来生成“报告”。
答案 1 :(得分:0)
似乎MySQL View无法使用预准备语句或存储过程。
您可以使用两个查询,其中一个提供人员列表,第二个提供生成的即时表B.
SELECT staff FROM A GROUP BY staff
然后遍历每个工作人员并为每个员工生成此字符串:
(SELECT sum(A2.time) FROM A as A2 WHERE date=A1.date AND staff="<staff>") AS <staff>,
然后生成此字符串在此查询中使用它:
SELECT A1.date,
<insert-generated-query-string-of-staff>
sum(time)
FROM A as A1 GROUP BY date;
这可能看起来像这样:
SELECT A1.date,
(SELECT SUM(A2.time) FROM A as A2 WHERE date=A1.date AND staff="John") AS John,
(SELECT SUM(A2.time) FROM A as A2 WHERE date=A1.date AND staff="Jeff") AS Jeff,
(SELECT SUM(A2.time) FROM A as A2 WHERE date=A1.date AND staff="James") AS James,
SUM(A1.time)
FROM A as A1 GROUP BY date;
与之前的方法类似,除了您通过MySQL而不是程序构建查询字符串。每次要生成表数据时都需要执行这些操作。
SELECT GROUP_CONCAT( DISTINCT CONCAT(
"(SELECT SUM(A2.time) FROM A as A2 WHERE date=A1.date AND staff=\"",
staff,
"\") AS ",
staff
) ) INTO @staff from A;
SET @table_b = CONCAT(
'SELECT A1.date, ',
@staff,
', SUM(A1.time) FROM A as A1 GROUP BY date'
);
PREPARE tableB from @table_b;
EXECUTE tableB;
我发现了其他一些想法,主要是准备好的陈述的例子 和/或存储过程,并提出了这个程序。
我认为这个更好,因为您不必重新创建查询 准备好的陈述。
DROP PROCEDURE generate_table_B;
DELIMITER //
CREATE PROCEDURE generate_table_B()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE staff_name VARCHAR(50) DEFAULT NULL;
DECLARE staff_list CURSOR FOR SELECT staff FROM A GROUP BY staff;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN staff_list;
SET @staff_stmts = '';
get_id: LOOP
FETCH staff_list INTO staff_name;
IF done = 1 THEN
LEAVE get_id;
END IF;
SET @staff_stmts = CONCAT(@staff_stmts, ' (SELECT SUM(A2.time) FROM A as A2 WHERE date=A1.date AND staff="', staff_name,'") AS ', staff_name,',');
END LOOP get_id;
CLOSE staff_list;
SET @table = CONCAT('SELECT A1.date, ', @staff_stmts, ' SUM(A1.time) FROM A as A1 GROUP BY date');
-- verifying the @table string generated
-- select @table;
PREPARE stmt FROM @table;
-- run @table
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
call generate_table_B();
这些是在列名,计算,查询或表之后指定的。
可以选择在其中一个之后使用AS
。
原因是嵌套查询。在这种情况下,如果我们没有使用 别名内部查询将从其查询与数据进行比较 从外部查询。根据具体情况,这可能是理想的 结果。但是,我们的查询显示它不是我们想要的。
> SELECT date,
-> (SELECT SUM(time) FROM A WHERE date=date AND staff="John") AS John,
-> (SELECT SUM(time) FROM A WHERE date=date AND staff="Jeff") AS Jeff,
-> (SELECT SUM(time) FROM A WHERE date=date AND staff="James") AS James,
-> SUM(time)
-> FROM A GROUP BY date;
+------+------+------+-------+-----------+
| date | John | Jeff | James | SUM(time) |
+------+------+------+-------+-----------+
| 1 | 9 | 8 | 4 | 10 |
| 2 | 9 | 8 | 4 | 11 |
+------+------+------+-------+-----------+
2 rows in set (0.01 sec)
现在您可能会注意到列SUM(time)
。这符合资格
计算,以便我们可以为此列设置别名,以便使用它更友好
选择时。像这样:
> SELECT date,
-> (SELECT SUM(time) FROM A WHERE date=date AND staff="John") AS John,
-> (SELECT SUM(time) FROM A WHERE date=date AND staff="Jeff") AS Jeff,
-> (SELECT SUM(time) FROM A WHERE date=date AND staff="James") AS James,
-> SUM(time) SummedTime
-> FROM A GROUP BY date;
+------+------+------+-------+------------+
| date | John | Jeff | James | SummedTime |
+------+------+------+-------+------------+
| 1 | 9 | 8 | 4 | 10 |
| 2 | 9 | 8 | 4 | 11 |
+------+------+------+-------+------------+
2 rows in set (0.01 sec)
+------+-------+------+------+--------------+
| date | James | jeff | john | SUM(A1.time) |
+------+-------+------+------+--------------+
| 1 | 2 | 3 | 5 | 10 |
| 2 | 2 | 5 | 4 | 11 |
+------+-------+------+------+--------------+
2 rows in set (0.00 sec)
> show create table A\G
*************************** 1. row ***************************
Table: A
Create Table: CREATE TABLE `A` (
`date` int(11) DEFAULT NULL,
`staff` varchar(50) DEFAULT NULL,
`tp` varchar(50) DEFAULT NULL,
`time` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
> SELECT * FROM A;
+------+-------+-------+------+
| date | staff | tp | time |
+------+-------+-------+------+
| 1 | john | bus | 3 |
| 1 | jeff | car | 3 |
| 1 | James | Train | 2 |
| 2 | Jeff | bus | 5 |
| 2 | john | car | 4 |
| 2 | james | train | 2 |
| 1 | john | train | 2 |
+------+-------+-------+------+
7 rows in set (0.00 sec)