按城市分组

时间:2011-07-07 07:46:57

标签: sql coldfusion group-by

作为I was advised by a good man and programmer我应该简化我的表格。到目前为止,我已经创建了一个新表(x-month,y-cities,value-Nettotal),但我仍然不明白为什么它不能按城市对值(nettotal)进行分组。月份没问题,但价值从左到右开始,没有留下任何0。无论如何,我希望你能从源头上理解一切:

这是查询:

<cfquery name="GET_SALES_TOTAL" datasource="#dsn#">
SELECT
    SUM(COALESCE(nettotal,0)) nettotal,
    SC.CITY_ID,
    DATEPART(MM,INVOICE_DATE) AY,
    C.FULLNAME,
    SC.CITY_NAME
FROM    
    #DSN2_ALIAS#.INVOICE I,
    SETUP_CITY SC,
    COMPANY C
WHERE
    C.COMPANY_ID=I.COMPANY_ID
    AND SC.CITY_ID=C.CITY
    AND PURCHASE_SALES=1
GROUP BY
    DATEPART(MM,INVOICE_DATE),
    SC.CITY_ID,
    C.FULLNAME,
    SC.CITY_NAME
ORDER BY 
      AY,CITY_ID
</cfquery>

<cfquery name="GET_SALES_GRAND_TOTAL" datasource="#dsn#">
SELECT SUM(NETTOTAL) NETTOTAL,SC.CITY_ID,SC.CITY_NAME
FROM #DSN2_ALIAS#.INVOICE I,SETUP_CITY SC,COMPANY C
WHERE C.COMPANY_ID=I.COMPANY_ID AND SC.CITY_ID=C.CITY AND PURCHASE_SALES=1
GROUP BY SC.CITY_ID, SC.CITY_NAME
ORDER BY CITY_ID,CITY_NAME
</cfquery>

这是表格本身:

<table cellpadding="3" cellspacing="1" class="color-border">
<tr class="color-header">
    <td></td>
    <cfoutput query="GET_SALES_GRAND_TOTAL" group="city_id">
        <td>#city_name#</td>
    </cfoutput>
</tr>
<cfoutput query="GET_SALES_TOTAL" group="AY"><!--- months first --->
    <tr class="color-row"><!--- month-specific stuff goes here --->
        <td>#ay#</td>
        <cfoutput group="city_id"><!--- city-specific stuff --->
            <td>#tlformat(nettotal,2)#<!--- format NETTOTAL however you want here ---></td>
        </cfoutput>
    </tr>
</cfoutput>
<tr class="color-header">
    <td>City Overal</td>
    <cfoutput query="GET_SALES_GRAND_TOTAL" group="city_id">
        <td>#tlformat(nettotal,2)#<!--- format NETTOTAL here ---></td>
    </cfoutput>
</tr>
</table>

这是截图,使其更加清晰:

screenshot

除了对城市进行分组之外的其他事情完美无缺!

3 个答案:

答案 0 :(得分:2)

看起来你遇到的问题是每个月份和城市的组合都没有记录。现在的设置很好,如果每个城市每个月都有销售,但我们可以改进这个代码,以便它正确处理“缺失”条目。

某些数据库具有特定的语法,可帮助您创建如下表:例如,Access具有TRANSFORM,Oracle和SQL服务器具有CUBEROLLUP,MySQL具有{{ 1}}。但是,即使在调整查询后,您仍可能需要调整CF,所以让我们尝试使用更通用的形式。

我们不需要内部联接,而是需要外部联接:所有城市以及任何拥有销售的城市的销售额。但是,我们还需要所有月份。在这个特定的例子中,我们可以使用笛卡尔积来获得月份和城市。 (要非常小心这些:你应该只在你确实想要一个记录用于字段A和字段B的每个组合的情况下使用它们。很容易在错误的地方使用一个并获得10,000个记录而不是100个。)< / p>

我们采取Johan's suggestion并修改一下:

WITH ROLLUP

我对其他内部连接存在的笛卡尔积的格式有点模糊,所以试一试,我们可以根据需要进行修改。

这应该为您提供一个查询,其中包含每个月的每个城市的销售额。外部联接的确切形式可能需要更改,具体取决于您使用的数据库,但这至少应该使您朝着正确的方向前进。

请注意,您需要更改您的CF以匹配修订后的查询,但我认为只是这一部分:

SELECT SUM(COALESCE(NETTOTAL,0)) NETTOTAL
  ,SC.CITY_ID
  ,SC.CITY_NAME
  ,M.INVOICE_MONTH                     
FROM SETUP_CITY SC
  LEFT OUTER JOIN COMPANY C ON SC.CITY_ID = C.CITY                   
  LEFT OUTER JOIN #DSN2_ALIAS#.INVOICE I ON C.COMPANY_ID = I.COMPANY_ID
  , (SELECT DISTINCT DATEPART(MM,INVOICE_DATE) INVOICE_MONTH FROM #DSN2_ALIAS#.INVOICE) M
WHERE PURCHASE_SALES = 1   
  AND DATEPART(MM,I.INVOICE_DATE) = M.INVOICE_MONTH                  
GROUP BY SC.CITY_ID, SC.CITY_NAME, M.INVOICE_MONTH
ORDER BY SC.CITY_NAME, M.INVOICE_MONTH 

成为

<cfoutput query="GET_SALES_TOTAL" group="AY"><!--- months first --->
    <tr class="color-row"><!--- month-specific stuff goes here --->
        <td>#ay#</td>

答案 1 :(得分:0)

SUM有一个令人讨厌的功能,即评估为null,其中一个求和值为null。

尝试将SELECT SUM(NETTOTAL) NETTOTAL更改为SELECT SUM(COALESCE(nettotal,0)) nettotal

备注查询语法

请不要使用隐式where联接,这些联接会让您感到困惑,容易出错并且对您的心理健康不利。
请改用显式联接:

SELECT SUM(NETTOTAL) NETTOTAL
  ,SC.CITY_ID
  ,SC.CITY_NAME                     
FROM #DSN2_ALIAS#.INVOICE I
  INNER JOIN SETUP_CITY SC ON SC.CITY_ID = C.CITY
  INNER JOIN COMPANY C ON C.COMPANY_ID = I.COMPANY_ID                   
WHERE PURCHASE_SALES = 1                     
GROUP BY SC.CITY_ID, SC.CITY_NAME                     
ORDER BY SC.CITY_NAME 

通过这种方式,您可以将连接条件与过滤条件分开,如果需要连接大量表格,则可以更轻松地维护和扩展查询。
作为奖励,您将从SQL '89中解脱出来,这样您最终可以离开Loveshack

答案 2 :(得分:0)

在ColdFusion中,当使用分组cfoutput时,您分组的任何列也应该位于查询的ORDER BY部分。因此,将第一个查询更改为ORDER BY AY, city_id 并将第二个查询更改为ORDER BY SC.CITY_NAME, city_id