Relative cost is only used to compare different plans for the same query. Relative cost is not useful for comparing two different queries.

Can you post screenshot of both queries with corresponding plans?

To add on what Dmitry said.

We need to see the query, its plan and corresponding classes with selectivity information.

For example, do you really want to run query without join condition?

select o.col1, o.col2, op.partnum, op.amount
from orders o join orderpositions op
where o.orderDate > $H-1000

CASE statement expects expression after THEN. DESC or ASC are not expressions. That's why you are getting syntax error.

So you need to supply some expression, ordering by which would mean reverse ordering by FirstName.

I don't know how to do this.

I would do sorting on the client or use dynamic SQL to create the query. As below for example.

Important! Nowhere I concatenate parameters of the stored procedure with the query to avoid SQL injections. Only SortingField is concatenated after checking that it has approved value.

ClassMethod Search(
    Name As %String = "",
    SSN As %String = "",
    Title As %String = "",
    SortingField As %String = "",
    StartIndex As %String = "") As %Integer [ SqlName = ExternalUsersSearch, SqlProc ]
{
 set query = "select Name, Title, SSN from Sample.Employee WHERE 1=1 "
 kill args

 if Name'="" {
     set args($I(args)) = Name
     set query = query _ "AND Name like ? "
 }

 if SSN'="" {
     set args($I(args)) = SSN
     set query = query _ "AND SSN like ? "
 }

 if Title'="" {
     set args($I(args)) = Title
     set query = query _ "AND Title like ? "
 }

 set AllowedFieldsToOrderBy = $LB("Name", "SSN", "Title")
 if $ListFind(AllowedFieldsToOrderBy, SortingField) {
    set query = query _ " ORDER BY " _ SortingField

    if StartIndex = 1 {
        set query = query _ " DESC"
    } else {
        set query = query _ " ASC"
    }
 }

 set rs = ##class(%SQL.Statement).%ExecDirect(,query,args...)

 #dim %sqlcontext As %SQLProcContext
 if rs.%SQLCODE >=0 {
     do %sqlcontext.AddResultSet(rs)
 } else { // pass errors to the caller
     set %sqlcontext.%SQLCODE = rs.%SQLCODE
     set %sqlcontext.%Message = rs.%Message
 }
 quit 1
}

I like usage of parameter, as it is computed once -- at compile time. And after you only fetch value in cycle.

You can also use $listfromstring via the same technique.

If you have index.csp and it is specified as login page and you are seeing 404 error, try following:

a) Enable Audit
b) Enable Protect event in Audit
c) Reproduce the problem.
e) Check Audit records if any Protect errors were logged

Name the file login.csp

And inside it check for Error:ErrorCode request parameter:

<html><head><title>Login</title></head>
<body>
My login page:</br>
<form method='post'>
Name: <input name="CacheUserName"/><br/>
Password: <input type='password' name="CachePassword"/><br/>
<input type='submit'/>
</form>

<server>
Set tMsg = $Get(%request.Data("Error:ErrorCode",1))
    If ((tMsg'="")&&($SYSTEM.Status.GetErrorCodes(tMsg)'[$$$ERRORCODE($$$RequireAuthentication))) {
        &html<<center>>
        write "Auth failed!"
        &html<</center>>
    }
</server>
</body>
</html>