web(cslai)

Findings and Notes in Web Development

Magic SQL

Ever wanted to find the number of days between two dates without counting weekend (Saturdays and Sundays)? In PHP you typically needs to do a lot of calculation and a lot of factors needs to be considered. Therefore, in the end you will end up having a whole bunch of code that you will probably start asking yourself whether you are programming a web-calendar or something similar.

I am currently working on a projects that deals with a lot of time-related data. My mind went completely blank when I am asked to do the above calculation without PHP code but a simple SQL statement. I was like ‘What??! That’s impossible…’. However, it is very much possible and at least there seems to be a few ways to do it in almost all DBMS on market.

No, there will be no stored procedure involved. You will know how later.

At first I was trying to write a super-duper-extremely complex SQL. But after flipping through my old Database Systems (Connolly & Begg, 2005) textbook (yes, I brought my super heavy database textbook to the office and just left there as my reference, I cannot program without reference), I made the first conclusion — the question given was insane. But if my supervisor already has the solution, then there must be a way to do it….

First, I search through a famous search engine and found this, but it is for SQL server.

Then, I tried to do some calculation with timestamp data with postgresql based on the documentation.
However, there doesn’t really work because I cannot ‘port’ the SQL statement for SQL server to PostgreSQL. So I need to get a better way of doing that.

Then I need to find a way for me to generate a list in a column so I can use a count() aggregate function. But does it even exists, none that I know of. So I made another search and got this. By combining tutorials and understanding from the documentation on date calculation, I then got the first query that looks like follows:-


SELECT count(s.a + date '2008-8-26') AS days
FROM generate_series(0, (date '2008-9-1' - date '2008-8-26')) as s(a)
WHERE EXTRACT(isodow FROM s.a + date '2008-8-26') < 6;

Alright, this doesn’t look very understandable, by comparing the answer provided by my supervisor (he published right before I posted mine). I got this


SELECT COUNT(*) AS total_days
FROM (SELECT date '2008-8-26' + generate_series(0, (date '2008-9-1' - date '2008-8-26')) as all_days) AS calendar
WHERE EXTRACT(isodow FROM all_days) < 6;

This is a much cleaner and understandable answer (The diff between two queries). However, this is not an optimal answer and takes 2ms to count the number of days without weekends in a year (source).

So, isn’t this solution better than a typical PHP code?

No Comments

No comments so far.

Leave Message

Personal Details

Toggle Extra

© 如无特别著名,本站的所有著作权归作者Jeffrey04以署名-非商业性使用-相同方式共享许可证发布。

本网志是由Wordpress荣誉呈现,站点界面SimKite设计归设计者Jeffrey04所有。

由于本站采用即时刊登留言者的留言,所以无法也不能完全监察所有的留言,站长Jeffrey04保留删除和不删除留言之权力。欢迎网友发表具建设性,负责任兼且合法之言论,否则已经发现立即删除而不另行通知。倘若网友发现留言出现问题请留言提出,本站保留一切法律权力。