计算不同行和不同列的持续时间?
Posted
技术标签:
【中文标题】计算不同行和不同列的持续时间?【英文标题】:Calcuate time duration in different row and different column? 【发布时间】:2020-02-12 07:56:59 【问题描述】:我想计算不同行和不同列的持续时间。这是我的示例数据:
'STATUSIN'(in second row) - 'STATUSOUT'(in first row)
我想将输出放在“LOSTTIME”列中
例如:
08:07:53 - 08:06:22 = 00:01:31 (OUTPUT)
这是我显示数据库数据的代码:
<asp:Repeater ID="rptrDAILYDATAWH" runat="server">
<HeaderTemplate>
<table class="table">
<thead>
<tr>
<th>NIP</th>
<th>NAME</th>
<th>DEPARTMENT</th>
<th>IN</th>
<th>OUT</th>
<th>LOSTTIME</th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<th><%# Eval("NIP") %></th>
<td><%# Eval("NAME") %></td>
<td><%# Eval("DEPARTMENT") %></td>
<td><%# Eval("STATUSIN") %></td>
<td><%# Eval("STATUSOUT") %></td>
<td><%# Eval("LOSTTIME") %></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</asp:Repeater>
这是后端的代码:
protected void BindDAILYDATWHARptr()
String CS = ConfigurationManager.ConnectionStrings["MANHOURConnectionString"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
using (SqlCommand cmd = new SqlCommand("SELECT * FROM DAILYDATAWH", con))
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
DataTable dtDaily = new DataTable();
sda.Fill(dtDaily);
rptrDAILYDATAWH.DataSource = dtDaily;
rptrDAILYDATAWH.DataBind();
【问题讨论】:
如果'STATUSOUT' <= 'STATUSIN'
会发生什么?
作为一般规则,避免使用SELECT *
,而是指定列名。如果您重新排序/重命名/删除列,这将有助于避免错误,因为这样您的查询就会中断,您会注意到您需要更早地更改代码。
对不起,我已经纠正了我的问题
如果一个用户在某一天拥有三种状态怎么办?
@SalmanA 这个数据只显示了 1 天,所以它的数据被过滤了 1 天。
【参考方案1】:
你基本上需要的是LAG
。阅读此article 了解更多信息。这适用于SQL Server 2012 onwards
。获得 prev 状态后,您可以在 C#
C#
运行时应用所需条件
SELECT NIP, NAME, DEPARTMENT, STATUSIN, STATUSOUT, LAG(STATUSIN,1) OVER(ORDER BY NIP, NAME, DEPARTMENT) PREVSTATUSIN FROM DAILYDATAWH
SQL Server 2008
的另一种解决方案是使用Self JOIN
SELECT a.NIP, a.NAME, a.DEPARTMENT, a.STATUSIN, a.STATUSOUT,
CONVERT(VARCHAR, CONVERT(TIME, b.STATUSIN - a.STATUSOUT), 108) LOSTTIME
FROM DAILYDATAWH a
LEFT JOIN DAILYDATAWH b ON a.ID = b.ID - 1 AND a.NIP = b.NIP AND a.NAME = b.NAME AND a.DEPARTMENT = b.DEPARTMENT
输出
要更新LOSTTIME
,你应该这样做
UPDATE a SET a.LOSTTIME = CONVERT(TIME, b.STATUSIN - a.STATUSOUT)
FROM DAILYDATAWH a
LEFT JOIN DAILYDATAWH b ON a.ID = b.ID - 1 AND a.NIP = b.NIP AND a.NAME = b.NAME AND a.DEPARTMENT = b.DEPARTMENT
【讨论】:
谢谢您,但是还有另一个不使用 LAG 的选项吗?因为我用的是sql server 2008,而LAG功能只是在sql server 2012中起作用 我不确定这个解决方案是否能解决上述问题。 @DeaAnandaLAG()
(及其对应的LEAD()
)是JOIN
的语法糖。您可以使用 ID 中的偏移量将表连接到自身以实现相同的目标。
@DeaAnanda,我添加了另一个解决方案,使用self join
来获取以前的记录。希望这会有所帮助
@TsahiAsher,是的,你是对的。在这里获取以前的记录是一个挑战,一旦你得到以前的值,添加if条件会更容易。【参考方案2】:
如果您使用的是 SQL Server,您可以根据需要参考以下脚本。
SELECT DATEADD(DAY,-1,GETDATE()) AS 'First_date', GETDATE() AS 'Second_date', FORMAT(DATEADD(ss,DATEDIFF(ss,'2020-02-10 10:30:00.143', '2020-02-11 14:22:20.683'),0),'hh:mm:ss') AS'区别'
【讨论】:
谢谢你帮助我,但我的意思不是输出【参考方案3】:由于您的数据中没有LOSTTIME
,您可以在转发器中计算:
变化:
<td><%# Eval("LOSTTIME") %></td>
到
<%# Convert.ToDateTime(Eval("STATUSOUT")) > Convert.ToDateTime(Eval("STATUSIN")) ? Convert.ToDateTime(Eval("STATUSOUT")).Subtract(Convert.ToDateTime(Eval("STATUSIN"))).ToString() : "-" %>
【讨论】:
谢谢你,很抱歉我已经更正了我的问题。我想把输出放在“LOSTTIME”列中 你不需要<%# Eval("LOSTTIME") %>
,你可以在中继器中这样做<%# Convert.ToDateTime(Eval("STATUSOUT")) > Convert.ToDateTime(Eval("STATUSIN")) ? Convert.ToDateTime(Eval("STATUSOUT")).Subtract(Convert.ToDateTime(Eval("STATUSIN"))).ToString() : "-" %>
不适合你?
谢谢,它的工作。但是,这不是我的意思的输出。请再次检查我的问题并查看示例数据,例如:08:07:53 - 08:06:22 = 00:01:31 (OUTPUT)
。它计算不同的列和不同的行
我的意思不是在同一行计算,我的意思是在不同的行计算,请再次检查有问题的图像以获取示例数据。计算'STATUSIN'(in second row) - 'STATUSOUT'(in first row)
以上是关于计算不同行和不同列的持续时间?的主要内容,如果未能解决你的问题,请参考以下文章