2

In ColdFusion, after having queried an MSSQL Database and added a couple of rows with the QueryAddRow function, I need to reorder the query by doing a query of a query. The order that I need requires that I use the CASE expression within the ORDER BY clause, like so:

<cfquery name="newquery" dbtype="query">
SELECT * FROM query
ORDER BY 
  CASE
    WHEN var LIKE 'All' THEN 'Zz'
    WHEN var LIKE '9%' THEN '0'
    ELSE var 
  END, year
</cfquery>

This returns an error: Error Executing Database Query. Caught an exception, type = Database. I've also attempted to use QueryExecute.

If I query the database directly, the query works just fine, so I only get an error when I attempt to do the query of a query. If I remove the CASE expression and just do (...) ORDER BY var, year the query of a query also works just fine, so it seems to me that CASE is not possible in a query of a query. Is this correct, or should I be able to use CASE somehow?

Here's the structure that I need to reorder (after having added three rows). Obviously I've removed all columns not relevant to the problem at hand.

year | var 
2001 | 9-12
2002 | 9-12
2003 | 9-12
2001 | 12+
2002 | 12+
2003 | 12+
2001 | All
2002 | All
2003 | All
2000 | 9-12
2000 | 12+
2000 | All

As you can see, I'm using CASE to order the var column by a custom ordering. I'm open to suggestions that might circumvent the issue altogether.

Please let me know if something is unclear.

SindreKjr
  • 249
  • 2
  • 17
  • 1
    "suggestions that might circumvent the issue altogether" If you have the ability to modify the table structure, add a column called "sortOrder" to the source table containing the "var" values and ORDER BY SortOrder instead. That would eliminate the need for CASE every time that column is used. Also, consider not using "var" as a column name. Since it is a reserved word in CFML, it may cause issues in some situations. – SOS Jan 16 '18 at 20:31
  • No worries, "var" is just a generic variable name I choose for the example, not one that I'm using in practice. Looks like all suggestions and answers point to making a sort-column, so that is probably what I'll go for. – SindreKjr Jan 17 '18 at 09:21
  • What are the three rows added manually? Asking cause there might be simpler options... – SOS Jan 17 '18 at 16:03

3 Answers3

5

Query of Queries only supports certain things - case constructs appear to one of those things it does not.

My suggestion is to use QueryAddColumn to add a sortBy column to your query object. Then loop through this query and assign appropriate values to this column. Then sort by this column in your Q of Q.

Alternatively, you could simply do what you said you were able to do and incorporate the logic in the original database query.

Dan Bracuk
  • 20,699
  • 4
  • 26
  • 43
1
  • Create a column containing your CASE expression.
  • Add this column before the asterisk
  • use Order By 1
Sparky
  • 14,967
  • 2
  • 31
  • 45
  • Downvoted. I tested your answer and it threw an error. – Dan Bracuk Jan 16 '18 at 13:23
  • 1
    And ordering by ordinal position is extremely brittle. If the query changes your order by may be on the wrong column. – Sean Lange Jan 16 '18 at 14:29
  • I agree Sean, it is not ideal, but is a work-around for this problem – Sparky Jan 16 '18 at 17:35
  • 1
    @Sparky, if you create a column containing the CASE expression, it's part of the results. So why not just sort by that column, instead of ORDER BY 1? :-) – SOS Jan 16 '18 at 20:34
  • Good point Ageax, probably bad habit on my part using ORDER BY – Sparky Jan 17 '18 at 14:26
  • @Sparky - Well, it's not always bad. I use it a lot in ad-hoc queries. It's a great time saver. No need to write out long ORDER BY statements. – SOS Feb 01 '18 at 16:33
1

Not being familiar with MSSQL (I use Oracle), it looks like you're creating a dummy sort column in the ORDER BY clause. Why not create the dummy sort column in the SELECT clause of the original MSSQL query? That way it will be already available already in the QoQ without any additional logic. Of course you'd then need either CFCASE or CFIF code to handle your QueryAddRow() statement.

Your initial MSSQL query would look like something like this.

<cfquery name="query" datasource="MSSQL_DSN">
SELECT
    year,
    ...,
    var,
    CASE
        WHEN var LIKE 'All' THEN 'Zz'
        WHEN var LIKE '9%' THEN '0'
        ELSE var 
    END, myDummySortCol
</cfquery>

Your QueryAddRow() would look like something this.

<cfif varToAdd eq "All">
    <cfset QueryAddRow(query, {year="#yearToAdd#", ..., var="#varToAdd#", myDummySortCol="Zz"})>
<cfelseif Left(varToAdd, 1) eq "9">
    <cfset QueryAddRow(query, {year="#yearToAdd#", ..., var="#varToAdd#", myDummySortCol="0"})>
<cfelse>
    <cfset QueryAddRow(query, {year="#yearToAdd#", ..., var="#varToAdd#", myDummySortCol="#varToAdd#"})>
</cfif>

Your QoQ would look like this.

<cfquery name="newquery" dbtype="query">
SELECT * FROM query
ORDER BY myDummySortCol
</cfquery>
Guest
  • 196
  • 3
  • Are you sure that `QueryAddRow` is the correct function for this situation? – Dan Bracuk Jan 16 '18 at 16:55
  • Yes, because the requirement in the original question states he needs to reorder the data via a QoQ after performing a series of `QueryAddRow()` statements to the original query. The solution I provided took that requirement into account. – Guest Jan 16 '18 at 17:52
  • Agree with the "adding a column to the SELECT", but ... it wasn't clear to me exactly what the three rows added are or what purpose they serve. So it is possible there's other ways to achieve the goal. @Basillicum can you clarify how/if they're related to the question? – SOS Jan 16 '18 at 20:33
  • 1
    Ageax -- I'm not the original poster so I don't know what adding the three rows are for. I answered the question based on his requirements that he has a query returned from MSSQL and then he adds 3 rows after the query is done and needs to resort using a QoQ. My solution creates a condition when adding the rows so that myDummySortCol contains the correct value for resorting. So I gave a complete answer based on the requirements posed in the question. – Guest Jan 16 '18 at 21:23
  • 1
    @Guest - I'm not knocking the answer :-) I understand why you answered the way you did. Can only go on the info provided. Just asking the OP for more clarification, as there might be other options... – SOS Jan 16 '18 at 21:56
  • 2
    @Ageax Sorry, I thought your comment was directed towards me :) Anyhow, as an addendum to your suggestion that the OP shouldn't use a variable named "var", I would also like to add that he probably shouldn't use a variable named "query". I can't find anything showing it's a reserved word, but it is too generic. – Guest Jan 16 '18 at 22:38