I have a SQL table BookChapters with over 20 millions rows. It has a clustered primary key (bookChapterID) and doesn\'t have any other keys or indexes. It takes miliseconds
If you have a look at the execution plans for your queries you would see what is going on.
Your first query if (select count(*) from BookChapters) = 0 is recognized by the query optimizer as the same as if exists(select * from BookChapters). SQL Server knows that the expression is true if there are at least one row present so it goes looking for the presence of one row instead of counting all the rows in the table.
For your other queries it can't be that smart and have to count the number of rows in the table before it can decide if the expression evaluates to true or false.