group by cities

梦想的初衷 提交于 2020-01-30 11:58:06

问题


As I was advised by a good man and programmer I should simplify my table. So far I have made a new table (x-month,y-cities,value-Nettotal) it works, but still I didn't understand why it can't group the values (nettotal) by cities. It's OK with month, but the values just come starting from left to right without any 0 left behind. Anyway I hope you will understand everything from the source:

here are the queries:

<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>

and here is the table itself:

<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>

Here is the screenshot to make it more clear:

The other stuff except grouping the cities works perfectly!


回答1:


It looks like the problem that you're having is that there is not a record for every combination of month and city. The setup as it is now is fine if every city has sales every month, but we can improve this code so that it handles "missing" entries properly.

Some databases have specific syntax that will help you make a table like this: for example, Access has TRANSFORM, Oracle and SQL server have CUBE and ROLLUP, MySQL has WITH ROLLUP. However, you still might have to tweak your CF even after adjusting the query, so let's try working with what you have in a more general form.

Instead of an inner join, we want an outer join: all cities plus sales for any city that has sales. However, we also need all months. In this particular instance, we can use a Cartesian product to get months and cities. (Be very careful about these: you should only use them in situations where you really do want one record for every combination of field A and field B. It's easy to use one in the wrong place and get 10,000 records instead of 100.)

Let's take Johan's suggestion and modify it some:

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 

I'm a little fuzzy on the format for a Cartesian product with other inner joins present, so give this a try and we can modify it as needed.

That should give you a query with a value for every city for each month with sales. The exact form of the outer join may need to change, depending on the database you're using, but that should at least move you in the right direction.

Note that you will need to change your CF to match the revised query, but just this part, I think:

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

becomes

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



回答2:


SUM has the annoying feature of evaluating to null is one of the summed values is null.

Try changing SELECT SUM(NETTOTAL) NETTOTAL to SELECT SUM(COALESCE(nettotal,0)) nettotal

Remark on query syntax

Please don't use implicit where joins they are confusing, error prone and bad for your mental health.
Use explicit joins instead:

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 

This way you can separate the join conditions from the filter conditions and your query will be much simpler to maintain and expand if you need to join lots of tables.
And as a bonus you will be unstuck from SQL '89 so you can finally leave the Loveshack.




回答3:


In ColdFusion, when using grouped cfoutput, whichever columns you group on should also be in the ORDER BY part of your query. So change the first query to have ORDER BY AY, city_id And change the second query to have ORDER BY SC.CITY_NAME, city_id



来源:https://stackoverflow.com/questions/6607421/group-by-cities

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!