首页 > 解决方案 > 对 select 子句中的一长串后续列执行计算的最佳方法

问题描述

我有一个表格,其中记录了每周不同员工的付款以及其他一些数据。

例如

Employee ID  | Upper Limit | ... | Week 1 | Week 2 | Week 3 | Week .. | ... | Week 52 | isActive |
8971239        70000               100      200      100      400             500       1
7823468        60000               200      300      100      200             400       1
8187119        20000               300      300      300      300             200       1

当我需要为特定员工计算所有周的总和时,以避免编写以下代码:

SELECT [Week 1] + [Week 2] + [Week 3] + ... + [Week 52] FROM tblWeeklySalaries where EmployeeID = 8971239

我正在循环中创建一个字符串,该字符串将用作要执行的脚本。像这样的东西:

DECLARE @script nvarchar(max)
SET @script = 'SET @periodou = (SELECT '

WHILE @tempWeek <= @week
BEGIN

    IF @tempWeek <= 52
    BEGIN
        SET @script = @script + 'ISNULL([Week ' + CONVERT(NVARCHAR, @tempWeek) + '], 0) +'  
    END
    SET @tempWeek = @tempWeek + 1
END

SET @script = LEFT(@script, LEN(@script) - 1)
SET @script = @script + ' AS [Salary] FROM tblWeeklySalaries 
                                      WHERE [EmployeeID ] = ' + CONVERT(NVARCHAR, @EmployeeID)

但是我不喜欢这种方式,因为创建字符串不容易处理,而且很多时候在要求更高的脚本中会变得非常复杂。

因此,我正在寻找一种在特定表中添加例如一系列列的方法。就像是

SELECT (COLUMNS(4, 56) FROM INFORMATION.SCHEMA WHERE TABLE_NAME = 'tblWeeklySalaries') FROM tblWeeklySalaries where EmployeeID = 8971239

有什么建议吗?非常感谢

标签: sqlsql-serveroptimizationquery-optimization

解决方案


你违反了假肢的第一个正常形式......后果将是:

  • 编写查询的困难
  • 表演的重大损失
  • 交易异常

您有多个列称为“周... n ”的事实意味着您想要相同信息的多个值,这些值因一个标准而异。

事实上,这可以被一个限制为 1 到 52 周的数组所取代。但第一个范式表示你应该始终在列中只有 ATOMIC 值。ARRAYS 包含多个值,因此它们不是原子的。通过使用表的这种结构,您有一个隐藏的数组。这是假体对第一范式的典型违反……</p>

在正确设计数据库时:

CREATE TABLE T_EMPLOYEE_PAYS 
(EMP_ID,    YEAR,    WEEK_NUMBER,    SALARY)

查询将很快编写:

SELECT EMP_ID,  YEAR,  SUM(SALARY)
FROM   T_EMPLOYEE_PAYS 
GROUP  BY EMP_ID,  YEAR

而且,您可以毫无困难地对其性能进行索引,并且不会丢失事务中的数据。

请记住,关系数据库不是电子表格


推荐阅读