我们可以在ColdFusion查询中使用“案例”吗?

时间:2018-11-02 11:37:31

标签: sql coldfusion coldfusion-2016 qoq

我在查询的ColdFusion查询中应用case,但抛出错误。

查询:

<cfquery name="qEmployees1" dbtype="query">
    select (
        case 
          when ISNUMERIC(u.userdefined)=1
          then right('00000000'+u.userdefined,8)
          else userdefined
        end
      ) as hello
    from all_employees
    order by hello ASC
</cfquery>

错误消息:

Encountered "when" at line 3, column 22. Was expecting one of: 
    "AND" ... "BETWEEN" ... "IN" ... "IS" ... "LIKE" ... "NOT" ... 
    "OR" ... ")" ... "=" ... "." ... "!=" ... "#" ... "<>" ... 
    ">" ... ">=" ... "<" ... "<=" ... "+" ... "-" ... "*" ... 
    "||" ... "/" ... "**" ... "(" ...

5 个答案:

答案 0 :(得分:2)

更新

由于最初的建议仅查看一行,因此不起作用。确实,您需要遍历all_employees记录集并将其应用于每个单独的行。

如果仅将结果输出到页面,则可能无需QoQ就可以实现此目标。像这样:

<cfoutput>
    <cfloop query="all_employees">
     <cfif isNumeric(all_employees.userdefined)>
      #Right('00000000'&all_employees.userdefined,8)#
     <cfelse>
      #all_employees.userdefined#
     <cfif>
    </cfloop>
</cfoutput>

原始答案:

这样的事情怎么样?:

<cfquery name="qEmployees1" dbtype="query">
SELECT 
<cfif isNumeric([all_employees].[u.userdefined])>
  right('00000000'+u.userdefined,8) 
<cfelse>
 u.userdefined
</cfif> AS hello
FROM all_employees
ORDER by hello
</cfquery>

我还没有对此进行测试,但是我认为在这种情况下,SQL列名称中的点符号不能正常工作。我还是把它放在方括号中。

答案 1 :(得分:1)

编辑:

我考虑过这一点,决定将其更改为实际答案。由于使用的是CF2016 +,因此可以使用CF提供的一些更现代的功能。首先,查询查询是一个很棒的工具,但是它可能非常很慢。特别是对于较低的记录数。然后,如果您的基本查询中有很多记录,由于它是内存操作,因此它可能会耗尽服务器的内存。我们不需要QoQ就可以实现我们的目标。

我们可以某种程度上重复您要寻找的功能的一种方法是使用一些较新的CF功能。 filtereachsort都在查询对象上工作。这些是它们的member function版本,但我认为它们看起来更干净。另外,我使用了cfscript语法。

我主要重用了原始的CFSCript查询(all_employees),该查询创建了查询对象,但是我向其中添加了一个f列,该列保留要过滤的文本。

all_employees = QueryNew("userdefined,hello,f", "varchar,varchar,varchar",
    [
      ["test","pure text","takeMe"],
      ["2","number as varchar","takeMe"],
      ["03","leading zero","takeMe"],
      [" 4 ","leading and trailing spaces","takeMe"],
      ["5        ","extra trailing spaces","takeMe"],
      ["        6","extra leading spaces","takeMe"],
      ["aasdfadsf","adsfasdfasd","dontTakeMe"],
      ["165e73","scientific notation","takeMe"],
      ["1.5","decimal","takeMe"],
      ["1,5","comma-delimited (or non-US decimal)","takeMe"],
      ["1.0","valid decimal","takeMe"],
      ["1.","invalid decimal","takeMe"],
      ["1,000","number with comma","takeMe"]

    ]
) ;

原始基本查询没有WHERE子句,因此没有对初始结果进行其他过滤。但是如果需要,我们可以使用QueryFilter.filter复制它。

filt = all_employees.filter( function(whereclause){ return ( whereclause.f == "takeMe"); } ) ;

这将使用all_employees查询并应用一个仅返回符合我们功能要求的行的功能。因此查询的任何行都在f == "takeMe"处。就像查询中的WHERE f = 'takeMe'。这样会将新过滤的结果设置到新的查询对象filt中。

然后,我们可以使用QueryEach.each遍历新过滤查询的每一行来修改我们需要的内容。在这种情况下,我们将为所需的值构建一个新的数组。 for/in循环可能会更快。我还没有测试。

filt.each(
        function(r) {
            retval.append(
                ISNUMERIC(r.userDefined) ? right("00000000"&ltrim(rtrim((r.userdefined))),8) : r.userDefined
            ) ;
        }
    )  ;

现在,我们有了一个带有所需结果的新数组,原始QoQ希望对这些结果进行排序。我们可以使用ArraySort.sort来做到这一点。

retval.sort("textnocase") ;

在我的测试中,CF2016似乎通过了retval.sort()作为布尔值,并且没有返回排序后的数组,但是CF2018了。这是预期的行为,因为返回类型在CF2018中已更改。无论如何,两者都将对retval数组进行排序,以便在我们转储retval数组时,它将按照选择的顺序进行。

正如我一直建议的那样,使用您的数据对系统进行负载测试。就像我说的那样,这只是进行尝试的一种方法。还有其他一些可能更快。

https://cffiddle.org/app/file?filepath=dedd219b-6b27-451d-972a-7af75c25d897/54e5559a-b42e-4bf6-b19b-075bfd17bde2/67c0856d-bdb3-4c92-82ea-840e6b8b0214.cfm

(CF2018)> https://trycf.com/gist/2a3762dabf10ad695a925d2bc8e55b09/acf2018?theme=monokai

https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-m-r/queryfilter.html

https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-m-r/queryeach.html

https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-a-b/arraysort.html

原始:

这不是评论,而是答案,但是评论太长了。

我想提几件事要提防。

首先,ColdFusion的isNumeric()有时会产生意想不到的结果。它实际上并不会检查值是否是数字。它检查字符串是否可以转换为数字。因此,isNumeric()会显示为numeric的各种值。例如:1e31000的科学符号。 isNumeric("1e3")将返回true

我的第二个建议是如何处理“数字”值(例如:" 4 ")中的前导和尾随空格。 isNumeric()将为此返回true,但是当您添加并修剪最终值时,它将以"000000 4"的形式出现。我的建议是在您的专栏中使用val()ltrim(rtrim())val()会将其简化为基本数字(" 1.0 " >> "1"),但是ltrim(rtrim())将保留该数字但消除空格(" 1.0 " >> "1.0"),并保留“科学计数法”值(" 1e3 " >> "1e3")。两者仍然都错过了1,000,因此,如果您对此感到担忧,则需要进行处理。但是,您使用的方法完全取决于数据包含的值。数字验证并不总是像看起来那样容易。

我一直是GIGO的坚定信奉者-垃圾回收,垃圾回收。我将基本数据清理视为工作的一部分。但是,如果它是极端的或常规的,我会告诉消息来源对其进行修复,否则他们的工作将无法正常进行。当涉及数据时,不可能考虑所有可能性,但是我们可以检查共同的期望。白名单总是比黑名单容易。

<cfscript>
all_employees = QueryNew("userdefined,hello", "varchar,varchar",
    [
      ["test","pure text"],
      ["2","number as varchar"],
      ["03","leading zero"],
      [" 4 ","leading and trailing spaces"],
      ["5        ","extra trailing spaces"],
      ["        6","extra leading spaces"],
      ["165e73","scientific notation"],
      ["1.5","decimal"],
      ["1,5","comma-delimited (or non-US decimal)"],
      ["1.0","valid decimal"],
      ["1.","invalid decimal"],
      ["1,000","number with comma"]

    ]
)

//writedump(all_employees) ;

retval = [] ;

for (r in all_employees) {
    retval.append(
        {
          "1 - RowInput"   : r.userdefined.replace(" ","*","all") , // Replace space with * for output visibility.
          "2 - IsNumeric?" : ISNUMERIC(r.userdefined) ,
          "3 - FirstOutput": ( ISNUMERIC(r.userDefined) ? right("00000000"&r.userdefined,8) : r.userDefined ) ,
          "4 - ValOutput"  : ( ISNUMERIC(r.userDefined) ? right("00000000"&val(r.userdefined),8) : r.userDefined ) ,
          "5 - TrimOutput"  : ( ISNUMERIC(r.userDefined) ? right("00000000"&ltrim(rtrim((r.userdefined))),8) : r.userDefined )
        } 
    ) ;
}

writeDump(retval) ;
</cfscript>

https://trycf.com/gist/03164081321977462f8e9e4916476ed3/acf2018?theme=monokai

答案 2 :(得分:1)

万一其他人决定尝试the QoQ below,要注意的一件非常重要的事情是,即使如果执行没有错误,它也不会做与CASE相同的事情。 CASE语句将逻辑应用于表的每一行中的值-分别。在QoQ版本中,CFIF表达式不会对查询中的所有值进行运算。它只检查第一行中的值,然后将对该值的决策应用于查询中的所有行。

请注意以下QoQ如何(错误地)报告所有值均为数字?虽然数据库查询(正确)报告了“数字”和“非数字”值的混合。因此,QoQ代码与CASE 等效。

测试表数据:

id  userDefined
1   22
2   AA
3   BB
4   CC

数据库查询:

   SELECT CASE
            WHEN ISNUMERIC(userDefined)=1 THEN 'Number: '+ userDefined
            ELSE 'Not a number: ' + userDefined
        END AS TheColumnAlias
   FROM TestTable
   ORDER BY ID ASC

数据库查询结果:

Database Query Result

季度

<cfquery name="qQueryOfQuery" dbtype="query">
  SELECT 
      <cfif isNumeric(qDatabaseQuery2.userDefined)>
         'Number: '+ userDefined
      <cfelse>
         'Not a number: ' + userDefined
      </cfif>
      AS TheColumnAlias
   FROM qDatabaseQuery2
   ORDER by ID
</cfquery>

QoQ结果

QoQ Result

答案 3 :(得分:0)

您到底想做什么?请分享您的帖子目标的背景信息。

在我看来,您的查询格式可能不正确。评估结果如下:

<cfabort>

尝试执行此操作。将<cfquery name="qEmployees1" dbtype="query"> select ( case when ISNUMERIC(u.userdefined)=1 then right('00000000'+u.userdefined,8) else userdefined end ) as hello from all_employees order by hello ASC <cfabort> </cfquery> 放在此处...然后让我知道您在运行查询时在屏幕上产生了什么查询。

grails.servlet.version = "3.0" // Change depending on target container compliance (2.5 or 3.0)
grails.project.class.dir = "target/classes"
grails.project.test.class.dir = "target/test-classes"
grails.project.test.reports.dir = "target/test-reports"
grails.project.target.level = 1.8
grails.project.source.level = 1.8
grails.project.war.file = "target/clinicaloutcome.war"
//grails.dependency.cache.dir = "target/ivy-cache"
//grails.dependency.cache.dir = "${user.home}/.ivy2/cache"
grails.tomcat.jvmArgs=["-Xms2048m",  "-Xmx2048m", "-XX:PermSize=2048m", "-XX:MaxPermSize=2048m"]
grails.project.dependency.resolution = {
    //    pom true
    // inherit Grails' default dependencies
    inherits("global") {
        // uncomment to disable ehcache
        // excludes 'ehcache'
    }
    log "warn" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose'
    checksums true // Whether to verify checksums on resolve

    repositories {
        inherits true // Whether to inherit repository definitions from plugins

        grailsPlugins()
        grailsHome()
        grailsCentral()
        mavenCentral()

        //mavenRepo "https://oss.sonatype.org/content/groups/public/"

        // uncomment these to enable remote dependency resolution from public Maven repositories
        mavenLocal()
        mavenRepo "https://oss.sonatype.org/content/repositories/releases/"
        mavenRepo "https://repo.grails.org/grails/plugins"
        mavenRepo "https://repo.grails.org/grails/core"
        mavenRepo "https://mvnrepository.com/artifact/"
        mavenRepo "https://mvnrepository.com/artifact/org.springframework/spring-test/"
        mavenRepo "http://repository.springsource.com/maven/bundles/release"
        mavenRepo "http://repository.springsource.com/maven/bundles/external"
        mavenRepo "http://snapshots.repository.codehaus.org"
        mavenRepo "http://repository.codehaus.org"
        mavenRepo "http://download.java.net/maven/2/"
        mavenRepo "http://repository.jboss.com/maven2/"

//        // Hardcoded path to the jar fields
//        flatDir name:'myRepo', dirs:'lib' 
    }
    dependencies {
        // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.

        runtime 'mysql:mysql-connector-java:5.1.20'


    }
    plugins {
        build ":release:2.2.1"


//        runtime ":hibernate:$grailsVersion"
        runtime ":hibernate4:4.3.5.3"
        runtime ":jquery:1.7.2"
        runtime ":resources:1.1.6"
        runtime ":cached-resources:1.0"     
        compile "org.grails.plugins:google-visualization:1.0.2"
        compile ":less-resources:1.3.3.2"
        compile ':app-info:1.0.1'
        compile ":svn:1.0.2"
        compile ":famfamfam:1.0.1"
        compile ":mail:1.0"
        compile ":spring-security-ui:0.2"
        compile ":spring-security-core:2.0-RC4"
        compile ":lang-selector:0.3"
        compile ":google-analytics:2.0"
        compile ":cache-headers:1.1.5"
        compile ":dynamic-controller:0.4"
        compile ":jquery-ui:1.8.15"
        compile ":events-push:1.0.M3"
        compile ":platform-core:1.0.M6"


        // Uncomment these (or add new ones) to enable additional resources capabilities
        runtime ":zipped-resources:1.0"
        runtime ":cached-resources:1.0"
        //runtime ":yui-minify-resources:0.1.4"

        build ":tomcat:7.0.53"
    }
}

答案 4 :(得分:0)

<cfquery name="qEmployees1" dbtype="query">
  SELECT 
    (
      <cfif isNumeric(all_employees.userdefined)>
         right('00000000'+all_employees.userdefined,8) 
      <cfelse>
         all_employees.userdefined
      </cfif>
    ) AS hello
FROM all_employees
ORDER by hello
</cfquery>

这是无语法的答案,这要归功于@volumeone