1

I am trying to do a ColdFusion Query of Query. The first query qEL returns several records. One of the rows is:

ELINKACCOUNTNUMBER                  WINACCNT                WSTREAMBUSINESSUNIT     WSTREAMOBJ  WSTREAMSUB
101-40001-0000-15-001-00000-0000    216000012.32103.1750    216000012               32103       1750 

Note in above: WSBusinessUnit value is 216000012, WSTREAMOBJ is 32103 and WSTREAMSUB is 1759

The second query is qEL2 which does return a bunch of records but only one row matches the record above with columns names of First, Second, and Third respectively.

So I need to do a join or something to and here is my code:

<cfquery name="qFinal" dbtype="query"> 
    SELECT 
       qEL.ELINKACCOUNTNUMBER AS ELAccountNum, qEL.WINACCNT AS WSAccountNum, qEL2.Description AS DESCRIPTION, qEL2.Posting_Edit_Code AS Posting_Edit_Code

    FROM 
        qEL, qEL2
    WHERE 
        qEL.WSTREAMBUSINESSUNIT =  <cfqueryparam value="#qEL2.First#" CFSQLType="cf_sql_varchar" />
    AND
        qEL.WSTREAMOBJ = <cfqueryparam value="#qEL2.Second#" CFSQLType="cf_sql_varchar" /> 
    AND 
        qEL.WSTREAMSUB = <cfqueryparam value="#qEL2.Third#" CFSQLType="cf_sql_varchar" /> 
</cfquery>

But this query doesn't return anything. Should I do a join instead somehow?

Thanks!

Edit 1: Maybe some syntax like this instead? Having trouble with a SQL Join in ColdFusion

Community
  • 1
  • 1
IrfanClemson
  • 1,699
  • 6
  • 33
  • 52
  • I recommend joining the tables instead of trying to map two separate queries to each other. This is what SQL is good at. Please post the table scheme of the relevant columns. – Alex Feb 15 '17 at 15:39

3 Answers3

1

To get started change this type of thing:

qEL.WSTREAMBUSINESSUNIT =  <cfqueryparam value="#qEL2.First#" CFSQLType="cf_sql_varchar" />

to this type of thing

qEL.WSTREAMBUSINESSUNIT =  qEL2.First

The query parameters are restricting your join to the first record of qEL2. Something else that might mess you up is whitespace. Make sure none of these values have leading or trailing spaces.

Dan Bracuk
  • 20,699
  • 4
  • 26
  • 43
  • I get error: Encountered "First. Incorrect conditional expression, Expected one of [like|null|between|in|comparison] condition, Unrecognized character in operand, – IrfanClemson Feb 15 '17 at 13:23
  • WHERE qEL.WSTREAMBUSINESSUNIT = #qEL2.First# AND qEL.WSTREAMOBJ = #qEL2.Second# AND qEL.WSTREAMSUB = #qEL2.Third# – IrfanClemson Feb 15 '17 at 13:27
  • leading spaces maybe problem, especially in 'First' column. I need to try TRIM somewhere – IrfanClemson Feb 15 '17 at 13:27
  • 1
    @Meengla - A) When comparing two columns, do not use pound signs or cfqueryparam. Those are only for when you are comparing the values in one column to a single, literal value, ie `WHERE qEL.someColumnName = 2` or `WHERE qEL.otherColumn = 'Bob'` . B) QoQ's are *extremely* rudimentary. They only support a limited subset of SQL, which does not include string functions like trim(). If needed, that must be done in the original database query. C) The word "First" is very likely to be a [reserved word](http://stackoverflow.com/questions/21226969/getting-queries-of-queries-error/21227662#21227662) – Leigh Feb 15 '17 at 14:09
  • 1
    D) Unlike some with database queries, QoQ string comparisons are case-sensitive. – Leigh Feb 15 '17 at 14:13
  • So in CFDump of all queries, the column names are returned all upper caps. That shouldn't matter in QoQ? – IrfanClemson Feb 15 '17 at 14:19
  • 1
    Nope. The column names can be any case in the QoQ. It is the values within the columns that matter. That is what is case sensitive. (BTW, the capitalization of the column names is legacy from early CF. CF always upper cases the `queryName.columnList` values. ) – Leigh Feb 15 '17 at 14:34
  • I can't believe I am unable to fix this for hours. I can SEE the matching values in both queries and they are numbers even if in string format. – IrfanClemson Feb 15 '17 at 14:37
  • Indeed, 'First' 'Second' and maybe 'Third' were giving errors as I stated above when no # around. I changed them to more meaningul – IrfanClemson Feb 15 '17 at 14:51
1

To expand on Dan's answer, there are a few issues that may be preventing the code from working:

  1. When comparing two columns, do not use pound signs orcfqueryparam. That syntax will end up comparing the values in one column to a single, literal value. For example:

    • WHERE qEL.someID = 2
    • WHERE qEL.firstName = 'Bob'

    To compare all of the values in one column to all of the values in another, use this syntax:

    WHERE someQuery1.ColumnName = otherQuery2.ColumnName

  2. QoQ's are extremely rudimentary. They only support a small subset of SQL that does not include things like outer joins or string functions like trim(). If needed, those must be done in the original database queries.

  3. The word "First" is very likely to be a reserved word and must be escaped with square brackets.

  4. Unlike some databases, string comparisons in QoQ's are case-sensitive.

    Unlike the rest of ColdFusion, Query of Queries is case-sensitive. However, Query of Queries supports two string functions, UPPER() and LOWER(), which you can use to achieve case-insensitive matching.

    Along those same lines, string comparisons are hyper sensitive to differences. So watch out for extra white space, as even a single tab or space difference can prevent a match.

  5. May not apply here, but check for data type differences. When comparing columns with different data types, the QoQ must convert both columns to the same data type first. Do not rely on implicit conversion. If needed, use and explicit CAST() to convert the columns to the appropriate data type. For example:

    • WHERE CAST(someQuery1.ColumnName AS INTEGER) = CAST(otherQuery2.ColumnName AS INTEGER)

    • WHERE CAST(someQuery1.ColumnName AS VARCHAR) = CAST(otherQuery2.ColumnName AS VARCHAR)

Finally, start small. Match on a single column first, and check the results. If it works, move to the next one. Otherwise, check the column data types and values to try and spot why things are not matching. Keep in mind browsers are famous for collapsing white space, so check the values character by character if needed.

Community
  • 1
  • 1
Leigh
  • 28,765
  • 10
  • 55
  • 103
  • Thank you. I think the culprit for non-return is probably that qEL2.Third has some empty values. I have changed the name to WSTREAMSUB and tried this: CAST(qEL.WSTREAMSUB AS INTEGER) = CAST(qEL2.WSBusinessSub AS INTEGER) but still getting error that cannot cast ''. Hmmm – IrfanClemson Feb 15 '17 at 16:25
  • 1
    (Edit - typo) You cannot use cfif in a QoQ that way, because it doesn't operate on all of the values in the query column, only the value in the first *row*. 1) What is the actual data type of the underlying columns? 2) When you say empty values, do you mean null or that this is some sort of varchar column and the value is literally an empty string "" (those are two different things) – Leigh Feb 15 '17 at 17:13
  • Yes sir. By catching for empty one in the WHERE clause as And length(RTRIM(GMSUB)) > 2 .. I now seem to be getting correct values. Fingers crossed!! – IrfanClemson Feb 15 '17 at 17:25
  • Cool. Oh the joys of string matching ;-) – Leigh Feb 15 '17 at 17:41
1

The problem is resolved based on the feedback/answer from @Dan Bracuk and @Leigh. Thank you all!

The problem of no-return had mostly to do with QEL2's Third column with blank values. So, in QEL2, I put this in the WHERE clauses:

And  length(RTRIM(GMSUB)) > 2

And, yes, I changed the column names in queries from first, second, third to more meaningful ones :)

So the WHERE clause now forces some values which are to be queried in the final query. And here is the final query--again, column names have been changed.

<cfquery name="qFinal" dbtype="query"> 
        SELECT 
        qEL.ELINKACCOUNTNUMBER AS ELAccountNum, qEL.WINACCNT AS WSAccountNum, qEL2.Description AS DESCRIPTION, qEL2.Posting_Edit_Code AS Posting_Edit_Code

        FROM 
        qEL, qEL2

        WHERE               
        CAST(qEL.WSTREAMBUSINESSUNIT AS INTEGER) = CAST(qEL2.WSBusinessUnit AS INTEGER)
        AND 
        CAST(qEL.WSTREAMOBJ AS INTEGER) = CAST(qEL2.WSBusinessObject AS INTEGER)
        AND
        CAST(qEL.WSTREAMSUB AS INTEGER) = CAST(qEL2.WSBusinessSub AS INTEGER) 


  </cfquery>

Thank you all! My Answer is definitely a combination of your feedback/inputs.

IrfanClemson
  • 1,699
  • 6
  • 33
  • 52
  • 1
    Thanks for posting the final answer for the next guy. BTW, you can get rid of this part, because it is not really doing what you think: ``. It compares the length of the values in the first row (only). – Leigh Feb 15 '17 at 18:27