Coldfusion查询查询

时间:2014-11-07 12:31:57

标签: sql database coldfusion

数据源的SQL查询工作正常。代码;

<cfquery name="GET_ACC_REMAINDER" datasource="#dsn2#">
    SELECT
        SUM(BAKIYE) AS BAKIYE, 
        SUM(BORC) AS BORC,
        SUM(ALACAK) AS ALACAK, 
        ACCOUNT_CODE,
        ACCOUNT_NAME,
        ACCOUNT_ID
    FROM
    (
    SELECT
        ROUND(SUM(ACCOUNT_ACCOUNT_REMAINDER.BORC - ACCOUNT_ACCOUNT_REMAINDER.ALACAK),2) AS BAKIYE, 
        ROUND(SUM(ACCOUNT_ACCOUNT_REMAINDER.BORC),2) AS BORC,
        ROUND(SUM(ACCOUNT_ACCOUNT_REMAINDER.ALACAK),2) AS ALACAK, 
        ACCOUNT_PLAN.ACCOUNT_CODE,
        ACCOUNT_PLAN.ACCOUNT_NAME,
    ACCOUNT_PLAN.ACCOUNT_ID,
    ACCOUNT_PLAN.SUB_ACCOUNT
    FROM
        (
        SELECT
            0 AS ALACAK,
             SUM(ROUND(ACCOUNT_CARD_ROWS.AMOUNT,2)) AS BORC,
            ACCOUNT_CARD_ROWS.ACCOUNT_ID    
        FROM
            ACCOUNT_CARD_ROWS,ACCOUNT_CARD
        WHERE
            BA = 0 AND ACCOUNT_CARD.CARD_ID=ACCOUNT_CARD_ROWS.CARD_ID
            AND ACTION_DATE BETWEEN  '2013-11-01 00:00:00' AND  '2013-11-30 00:00:00' GROUP BY
            ACCOUNT_CARD_ROWS.ACCOUNT_ID
        HAVING SUM(ROUND(ACCOUNT_CARD_ROWS.AMOUNT,2))<>0
    UNION ALL
        SELECT
             SUM(ROUND(ACCOUNT_CARD_ROWS.AMOUNT,2)) AS ALACAK,
            0 AS BORC,
            ACCOUNT_CARD_ROWS.ACCOUNT_ID        
        FROM
            ACCOUNT_CARD_ROWS,
            ACCOUNT_CARD
        WHERE
            BA = 1 AND ACCOUNT_CARD.CARD_ID=ACCOUNT_CARD_ROWS.CARD_ID       
            AND ACTION_DATE BETWEEN  '2013-11-01 00:00:00' AND  '2013-11-30 00:00:00' GROUP BY
            ACCOUNT_CARD_ROWS.ACCOUNT_ID            
        HAVING SUM(ROUND(ACCOUNT_CARD_ROWS.AMOUNT,2))<>0 
        UNION ALL
            SELECT DISTINCT
                0 AS ALACAK,
                0 AS BORC,
                ACCOUNT_PLAN.ACCOUNT_CODE
            FROM
                ACCOUNT_PLAN,
                ACCOUNT_PLAN ACCOUNT_ACCOUNT_REMAINDER
            WHERE
                ACCOUNT_PLAN.ACCOUNT_CODE NOT IN 
                                    (SELECT 
                                        ACCOUNT_ID 
                                    FROM 
                                        ACCOUNT_CARD_ROWS,
                                        ACCOUNT_CARD
                                    WHERE
                                        ACCOUNT_PLAN.ACCOUNT_CODE = ACCOUNT_CARD_ROWS.ACCOUNT_ID AND
                                        ACCOUNT_CARD_ROWS.CARD_ID = ACCOUNT_CARD.CARD_ID
                                        AND ACCOUNT_CARD.ACTION_DATE BETWEEN  '2013-11-01 00:00:00' AND  '2013-11-30 00:00:00' )

                AND ACCOUNT_PLAN.ACCOUNT_CODE = LEFT(ACCOUNT_ACCOUNT_REMAINDER.ACCOUNT_CODE,3)

        )
        AS ACCOUNT_ACCOUNT_REMAINDER,
        ACCOUNT_PLAN
    WHERE
        1=1
        AND  ACCOUNT_PLAN.ACCOUNT_CODE = LEFT(ACCOUNT_ACCOUNT_REMAINDER.ACCOUNT_ID,3)
    GROUP BY    
        ACCOUNT_PLAN.ACCOUNT_CODE, 
        ACCOUNT_PLAN.ACCOUNT_NAME,
    ACCOUNT_PLAN.ACCOUNT_ID,
    ACCOUNT_PLAN.SUB_ACCOUNT    
    )T1
    GROUP BY
        ACCOUNT_CODE, 
        ACCOUNT_NAME,
        ACCOUNT_ID,
        SUB_ACCOUNT     
    ORDER BY    
        ACCOUNT_CODE
</cfquery>

这个查询太慢了。为此,我尝试使用查询查询。我编了一些东西。

<cfquery name="ACCOUNT_PLAN" datasource="#dsn2#">
select * from ACCOUNT_PLAN
</cfquery>
<cfquery name="ACCOUNT_CARD" datasource="#dsn2#">
select * from ACCOUNT_CARD
</cfquery>
<cfquery name="ACCOUNT_CARD_ROWS" datasource="#dsn2#">
select * from ACCOUNT_CARD_ROWS
</cfquery>
<cfquery name="GET_ACC_REMAINDER" dbtype="query">
    SELECT
        SUM(BAKIYE) AS BAKIYE, 
        SUM(BORC) AS BORC,
        SUM(ALACAK) AS ALACAK, 
        ACCOUNT_CODE,
        ACCOUNT_NAME,
        ACCOUNT_ID
    FROM
    (
    SELECT
        ROUND(SUM(ACCOUNT_ACCOUNT_REMAINDER.BORC - ACCOUNT_ACCOUNT_REMAINDER.ALACAK),2) AS BAKIYE, 
        ROUND(SUM(ACCOUNT_ACCOUNT_REMAINDER.BORC),2) AS BORC,
        ROUND(SUM(ACCOUNT_ACCOUNT_REMAINDER.ALACAK),2) AS ALACAK, 
        ACCOUNT_PLAN.ACCOUNT_CODE,
        ACCOUNT_PLAN.ACCOUNT_NAME,
    ACCOUNT_PLAN.ACCOUNT_ID,
    ACCOUNT_PLAN.SUB_ACCOUNT
    FROM
        (
        SELECT
            0 AS ALACAK,
             SUM(ROUND(ACCOUNT_CARD_ROWS.AMOUNT,2)) AS BORC,
            ACCOUNT_CARD_ROWS.ACCOUNT_ID    
        FROM
            ACCOUNT_CARD_ROWS,ACCOUNT_CARD
        WHERE
            BA = 0 AND ACCOUNT_CARD.CARD_ID=ACCOUNT_CARD_ROWS.CARD_ID
            AND ACTION_DATE BETWEEN  '2013-11-01 00:00:00' AND  '2013-11-30 00:00:00' GROUP BY
            ACCOUNT_CARD_ROWS.ACCOUNT_ID
        HAVING SUM(ROUND(ACCOUNT_CARD_ROWS.AMOUNT,2))<>0
    UNION ALL
        SELECT
             SUM(ROUND(ACCOUNT_CARD_ROWS.AMOUNT,2)) AS ALACAK,
            0 AS BORC,
            ACCOUNT_CARD_ROWS.ACCOUNT_ID        
        FROM
            ACCOUNT_CARD_ROWS,
            ACCOUNT_CARD
        WHERE
            BA = 1 AND ACCOUNT_CARD.CARD_ID=ACCOUNT_CARD_ROWS.CARD_ID       
            AND ACTION_DATE BETWEEN  '2013-11-01 00:00:00' AND  '2013-11-30 00:00:00' GROUP BY
            ACCOUNT_CARD_ROWS.ACCOUNT_ID            
        HAVING SUM(ROUND(ACCOUNT_CARD_ROWS.AMOUNT,2))<>0 
        UNION ALL
            SELECT DISTINCT
                0 AS ALACAK,
                0 AS BORC,
                ACCOUNT_PLAN.ACCOUNT_CODE
            FROM
                ACCOUNT_PLAN,
                ACCOUNT_PLAN ACCOUNT_ACCOUNT_REMAINDER
            WHERE
                ACCOUNT_PLAN.ACCOUNT_CODE NOT IN 
                                    (SELECT 
                                        ACCOUNT_ID 
                                    FROM 
                                        ACCOUNT_CARD_ROWS,
                                        ACCOUNT_CARD
                                    WHERE
                                        ACCOUNT_PLAN.ACCOUNT_CODE = ACCOUNT_CARD_ROWS.ACCOUNT_ID AND
                                        ACCOUNT_CARD_ROWS.CARD_ID = ACCOUNT_CARD.CARD_ID
                                        AND ACCOUNT_CARD.ACTION_DATE BETWEEN  '2013-11-01 00:00:00' AND  '2013-11-30 00:00:00' )

                AND ACCOUNT_PLAN.ACCOUNT_CODE = LEFT(ACCOUNT_ACCOUNT_REMAINDER.ACCOUNT_CODE,3)

        )
        AS ACCOUNT_ACCOUNT_REMAINDER,
        ACCOUNT_PLAN
    WHERE
        1=1
        AND  ACCOUNT_PLAN.ACCOUNT_CODE = LEFT(ACCOUNT_ACCOUNT_REMAINDER.ACCOUNT_ID,3)
    GROUP BY    
        ACCOUNT_PLAN.ACCOUNT_CODE, 
        ACCOUNT_PLAN.ACCOUNT_NAME,
    ACCOUNT_PLAN.ACCOUNT_ID,
    ACCOUNT_PLAN.SUB_ACCOUNT    
    )T1
    GROUP BY
        ACCOUNT_CODE, 
        ACCOUNT_NAME,
        ACCOUNT_ID,
        SUB_ACCOUNT     
    ORDER BY    
        ACCOUNT_CODE
</cfquery>

Coldfusion调试显示此错误。

执行数据库查询时出错。 查询查询语法错误。 遇到“(。 错误发生在第10行。

你有什么想法吗?

2 个答案:

答案 0 :(得分:9)

查询查询不支持子查询。

答案 1 :(得分:3)

Stormcloak,我看到你要做的是什么,但你的第一个努力应该是尝试确定原始查询为何缓慢。如果你想通过Q的Q来做这个,你就不能(正如Dan所说)使用子查询。 Q的Q支持相当谨慎的命令和语法子集。不支持从q的q的子查询中选择。

但是,如果您想利用Q的Q 并且愿意将子查询逻辑移动到代码,那么可以做类似这样的伪代码:< / p>

<cfquery name="ACCOUNT_PLAN" datasource="#dsn2#">
select * from ACCOUNT_PLAN
</cfquery>
<cfquery name="ACCOUNT_CARD" datasource="#dsn2#">
select * from ACCOUNT_CARD
</cfquery>
<cfquery name="ACCOUNT_CARD_ROWS" datasource="#dsn2#">
select * from ACCOUNT_CARD_ROWS
</cfquery>

<!---MAK:   get the unique account_ids--->
<cfquery name="getIDs" dbtype="query">
    SELECT UNIQUE ACCOUNT_ID
    FROM    ACCOUNT_PLAN  
</cfquery>


<Cfset GET_ACC_REMAINDER = querynew("BAKIYE,BORC,ALACAK,ACCOUNT_CODE,ACCOUNT_NAME,ACCOUNT_ID","decimal,decimal,decimal,varchar,varchar,varchar")/>

<cfloop query="getIDs">
    <!---MAK:   Pull out a subset of data based on account_ID--->
    <cfquery name="getPlans" dbtype="query">
        SELECT * FROM ACCOUNT_PLAN  
        WHERE    account_id = '#account_id#'    
    </cfquery>
    <cfquery name="getCards" dbtype="query">
        SELECT * FROM ACCOUNT_CARD  
        WHERE    account_id = '#account_id#'    
    </cfquery>
    <cfquery name="getPlans" dbtype="query">
        SELECT * FROM ACCOUNT_CARD_ROWS  
        WHERE    account_id = '#account_id#'    
    </cfquery>

    Now, using implement your logic using these subqueries - probably with a block of code to calculate BAKIYE, BORC, AND ALACAK - 

    <cfset BAKIYE = 0/>
    <!---MAK:   Block 1 - calculate BAKIYE--->  
    ... code for BAKIYE goes here

    <cfset BORC = 0/>
    <!---MAK:   block 2 calculate BORC--->
    ... code for BORC...

    <cfset ALACAK = 0/>
    <!---MAK:   block 3 calclate ALACAK--->
    ... code for ALACAK 

    Final step:

    <cfset querysetcell(GET_ACC_REMAINDER,"BAKIYE",BAKIYE)/>
    <cfset querysetcell(GET_ACC_REMAINDER,"BORC",BORC)/>
    <cfset querysetcell(GET_ACC_REMAINDER,"ALACAK",ALACAK)/>
    <cfset querysetcell(GET_ACC_REMAINDER,"ACCOUNT_CODE",getPlans.ACCOUNT_CODE)/>
    <cfset querysetcell(GET_ACC_REMAINDER,"ACCOUNT_NAME",getplans.ACCOUNT_NAME)/>
    <cfset querysetcell(GET_ACC_REMAINDER,"ACCOUNT_ID",ACCOUNT_ID)/>

</cfloop>

最终结果是一个查询,GET_ACC_REMAINDER填充了复杂的union / subquery中的值。

这将涉及重新设计复杂联合查询中的逻辑 - 这超出了堆栈溢出解决方案的范围 - 但是你明白了。考虑到你的查询的复杂性,我认为这是一项艰巨的任务,我会确保并且质疑这一点。这个逻辑不仅是多毛的,而且DB处理数字的方式也可能与Java处理它的方式不同 - 所以这是另一个需要考虑的问题。

注意,您可能还需要在原始查询中获取表格 - 我注意到ACCOUNT_ACCOUNT_REMAINDER例如我似乎无法识别为聚合 - 所以也许它是一个表格。毫无疑问,您需要在每个块内部添加q,数学运算和IF elses以进行计算。

现在问题可能是应该你这样做了(我有点回答我的所有鸡肉小心谨慎)?我可能会在亚当的营地,并建议反对它。从性能角度来看,它可能不会为您节省太多 - 特别是如果您必须在数据库中访问逻辑块中的其他数据。最后它可能会变慢。它逻辑,这种东西存在于DB服务器上,它配备了这种复杂的逻辑。我可能会花时间调整服务器上的查询或者将其重写为带有临时表的存储过程。

Q的Q是一个很棒的工具,但对于你如何使用它来说还不够复杂:)