作为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>
这是截图,使其更加清晰:
除了对城市进行分组之外的其他事情完美无缺!
答案 0 :(得分:2)
看起来你遇到的问题是每个月份和城市的组合都没有记录。现在的设置很好,如果每个城市每个月都有销售,但我们可以改进这个代码,以便它正确处理“缺失”条目。
某些数据库具有特定的语法,可帮助您创建如下表:例如,Access具有TRANSFORM
,Oracle和SQL服务器具有CUBE
和ROLLUP
,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