如何计算或求和String列值

时间:2011-02-21 18:52:01

标签: sql sql-server tsql sql-server-2008

从第1天到第31天,我有员工出勤表,列名为1,2,3,4 5 ..... 31 和数据类型是nVarchar(5)

我在这些列(P,H,A)中添加值,例如:

P =现在 A =缺席 H =假期

现在我想计算最后一列中的Total(P = Present),即Employee的[TotalPresnets]。 如何计算(计算)字符串值。

5 个答案:

答案 0 :(得分:4)

因为您创建了31列,所以每种类型的操作都涉及获取所有31列。这是为什么这个设计会给你带来很多痛苦的一百万个原因之一。所以,我不得不说你需要考虑改变这个设计!

如果你必须坚持这一点,你将得到类似这样的代码:

select
    EmployeeID,
    (
        case when Day0 = 'P' then 1 else 0 end
        + case when Day1 = 'P' then 1 else 0 end
        + case when Day2 = 'P' then 1 else 0 end
        ...
        + case when Day31 = 'P' then 1 else 0 end
    ) as TotalPresent
from
    Attendance

另一个丑陋的解决方案是使用动态SQL生成上面的查询。

一般来说,当你被迫陷入如此丑陋的解决方案时,这是一个很好的迹象表明你正在接近这个问题。

另请注意,对于单行的非常基本的操作,这是大约40行代码。将此技术应用到您的应用程序的其余部分将导致更多的麻烦。想象一下,如果你必须改变这里的任何逻辑;什么应该是一行现在31。

更好的设计将产生更直观/可维护/可读的代码:

select
    EmployeeID,
    count(*) TotalPresent
from
    EmployeeDailyAttendance eda
    inner join Days d on d.ID = eda.DayID
where
    eda.Code = 'p'
group by
    EmployeeID

答案 1 :(得分:1)

SQL Server 2008非常棒。看看这个例子:

讨论表

create table attendance(
empid int,
[1] char(1), [2] char(1), [3] char(1), [4] char(1),
[5] char(1), [6] char(1), [7] char(1), [8] char(1));

insert attendance values
(1,'P','P','H','A','A','P','P','P'),
(2,'P','P','P','P','P','P','P',null),
(3,'P','P','H','P','P','P',null,null);

您的选择语句选项(根据需要扩展为31天)

嵌套选择

select empid,
 (select COUNT(*)
  from (values([1]),([2]),([3]),([4]),([5]),([6]),([7]),([8])) t(Day)
  where Day='P')
from attendance

逆透视

select empid, count(day)
from attendance
unpivot (type for day in ([1],[2],[3],[4],[5],[6],[7],[8])) unp
where type='P'
group by empid

答案 2 :(得分:0)

我必须同意马克的意见。您当前的设计使得按日期查询非常困难。我建议使用日期字段和状态字段。每个员工每天都会有一行,但是要获得您正在寻找的结果会更容易。

答案 3 :(得分:0)

我知道人们所说的是真的。尽管如此,你很可能很快就会完成这个项目,所以我想我会帮你一把。

<?php

$result = mysql_query("SELECT * FROM table WHERE month = '$month'");

// loop through rows. 
while(false !== ($row = mysql_fetch_object())) {
    // loop through cols
    foreach($row as $key => $col) {
        if($key != $userID)
        $split = str_split($col);
        // loop through letters
        foreach($split as $letter) {
            $final_results[$row->userID][$letter]++;
        }
    }
}

print_r($final_results);

/*
 * outputs something like
 * array(
 *  '15' => array(
 *      'P' => 19,
 *      'A' => 4,
 *      'H' => 1
 * )
 *  '13' => array(
 *      'P' => 19,
 *      'A' => 4,
 *      'H' => 1
 * )
 * );
*/

很可能你不使用PHP而是使用其他语言,但这个想法很简单。循环遍历所有列,仅跳过非天数的列,将每个字母相加并将其存储到数组中。

希望这对你有用。

此致 佩德罗

答案 4 :(得分:0)

我发表了评论,但认为答案可能会更好。

创建表格视图:

SELECT EmployeeID, '1' As DayOfMonth, Day1 As AttendanceValue FROM TableName
UNION
SELECT EmployeeID, '2', Day2 FROM TableName
....
SELECT EmployeeID, '31', Day31 FromTableName

现在您可以使用类似于tenfour的查询:

SELECT AttendanceValue, COUNT(AttendanceValue) FROM ViewName GORUP BY AttendanceValue