在 SQL 中迭代日期
我有一个看起来有点像这样的数据表:
Name StartTime FinishTime Work
Bob 2010-08-03 08:00:00 2010-08-03 12:00:00 4
Bob 2010-08-03 13:00:00 2010-08-03 16:00:00 3
Pete 2010-08-04 08:00:00 2010-08-04 12:00:00 4
Mark 2010-08-04 10:00:00 2010-08-04 12:00:00 2
这些日期范围都不应该跨越午夜。
我想编写 SQL,它会给我以下输出,给定输入开始日期 2010-08-02 和结束日期 2010-08-05
Date Name TotalWork
2010-08-03 Bob 7
2010-08-03 Pete 3
2010-08-04 Pete 4
2010-08-04 Mark 2
我可以接受,实际上可能最终需要,有任何日子没有关联的工作也会在结果集中表示,可能作为这样的行:
2010-08-05 NULL 0
我不太确定如何以与其他语言相同的方式在 SQL 中迭代日期。
为了提供一些上下文,其输出最终将插入到 Stacked Chart .Net 控件中。
有人可以给我一些线索、教程链接或其他帮助吗?否则我想我会摆弄这个好几天!
谢谢你!
乔纳森
I have a table of data that looks a bit like this:
Name StartTime FinishTime Work
Bob 2010-08-03 08:00:00 2010-08-03 12:00:00 4
Bob 2010-08-03 13:00:00 2010-08-03 16:00:00 3
Pete 2010-08-04 08:00:00 2010-08-04 12:00:00 4
Mark 2010-08-04 10:00:00 2010-08-04 12:00:00 2
None of these date ranges should ever span over midnight.
I want to write SQL that will give me the following output, given an input Start Date of 2010-08-02 and a Finish Date of 2010-08-05
Date Name TotalWork
2010-08-03 Bob 7
2010-08-03 Pete 3
2010-08-04 Pete 4
2010-08-04 Mark 2
I could live with, and in fact may ultimately need, to have any days that do not have work associated also be represented in the results set, maybe as a row like this:
2010-08-05 NULL 0
I'm not quite sure how to iterate through dates in SQL in the same way that I would with other languages.
To give this some context, the output of this will ultimately plug into a Stacked Chart .Net control.
Could someone give me a clue, a link to a tutorial or some other help? Otherwise I think I'll be fiddling with this for days!
Thank you!
Jonathan
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
试试这个:
要获得缺失的日子比较困难。
编辑,我正在通过使用通用表表达式(CTE)的解决方案重新审视这一点。这不需要使用日期表。
Try this:
To get the missing days is harder.
EDIT, I am revisiting this with a solution that uses a Common Table Expression (CTE). This does NOT require use of a dates table.
在 SQL 中迭代行的方式是不这样做的。 SQL 是一种基于集合的语言,需要与其他过程语言完全不同的思维方式。如果您要使用 SQL,您确实需要能够转变思维方式才能取得成功。
以下是我处理这个问题的方法:
此外,您的表设计看起来违反了正常的数据库设计标准。您的“工作”列实际上只是 StartTime 和 FinishTime 之间的计算。这使得它成为相同数据的重复,这可能会导致各种问题。例如,当您的 StartTime 和 FinishTime 相差 4 小时,但“工作”显示 5 小时时,您会怎么做?
要包含没有关联工作的日期,您需要在前端处理它,或者需要一个“日历”表。它将包含所有日期,您将与您的表进行 LEFT JOIN 操作。例如:
日历表还允许您向日期添加附加信息,例如假期标记、“加班”天(周日的工作时间可能算作半天)等。
注意:Charles Bretana 的解决方案可能更干净一些,因为它将数据类型保留为日期时间,而不是将它们转换为字符串。对于其他一些评论,我将把它留在这里。
The way that you iterate through rows in SQL is that you don't. SQL is a set-based language which requires a whole different mindset from other procedural languages. If you're going to be working with SQL you really need to be able to make that shift in thinking to be successful.
Here's how I would handle this one:
Also, your table design looks like it violates normal database design standards. Your "work" column is really just a calculation between the StartTime and FinishTime. That makes it a duplication of the same data, which can cause all sorts of problems. For example, what do you do when your StartTime and FinishTime are 4 hours apart, but the "Work" says 5 hours?
To include dates with no work associated, you'll need to either handle that in the front end, or you'll need a "Calendar" table. It would have all of the dates in it and you would do a LEFT JOIN to that with your table. For example:
The calendar table also allows you to add additional information to the dates, such as a flag for holidays, "overtime" days (maybe work counts as time and a half on Sundays), etc.
NOTE: Charles Bretana's solution is probably a little bit cleaner since it keeps the data types as datetimes instead of turning them into strings. I'm going to leave this here though for some of the other comments.