SQL query syntax errors when dealing with subpopulations - sql

I'm a software tester using this SQL query to check some data in our db:
select * from (
select sum(case when qm.HEALTHY_TERM_NEWBORN='E' then 1 else 0 end) as num, -- choose measure status columns here as appropriate
sum(case when qm.HEALTHY_TERM_NEWBORN in ('D','E') then 1 else 0 end) as denom,
-- summary level columns
cms.FACILITY_GROUP_ID,
-- time period columns
dt.USA_FISCAL_YEAR_BEGIN_DT
from F_MU_QM_EH_2014_IP_ADMSN qm
inner join CMS_MU_INFO cms on qm.DISCHARGE_CMS_MU_ID=cms.CMS_MU_ID
inner join DATE_DIMENSION dt on dt.CALENDAR_DT=qm.DISCHARGE_DATE
-- do filtering here if any
where cms.FACILITY_GROUP_ID='130170' AND dt.USA_FISCAL_YEAR_BEGIN_DT='10/01/2013'
group by -- summary level grouping
cms.FACILITY_GROUP_ID,
-- time period grouping
dt.USA_FISCAL_YEAR_BEGIN_DT
) x
where denom is not null
The script returns aggregated data from one column of information; however, for some of my testing I need to filter the column based on another column that defines a subpopulation within the first column. I tried this:
select * from (
sum(case when qm.SCIPINF1='E' and qm.SCIPINF1_POPULATION_C=7 then 1 else 0 end) as num
sum(case when qm.SCIPINF1 in ('D','E') and qm.SCIPINF1_POPULATION_C=1 then 1 else 0 end) as denom
-- summary level columns
cms.FACILITY_GROUP_ID,
-- time period columns
dt.USA_FISCAL_YEAR_BEGIN_DT
from F_MU_QM_EH_2014_IP_ADMSN qm
inner join CMS_MU_INFO cms on qm.DISCHARGE_CMS_MU_ID=cms.CMS_MU_ID
inner join DATE_DIMENSION dt on dt.CALENDAR_DT=qm.DISCHARGE_DATE
-- do filtering here if any
where cms.FACILITY_GROUP_ID='130170' AND dt.USA_FISCAL_YEAR_BEGIN_DT='10/01/2013'
group by -- summary level grouping
cms.FACILITY_GROUP_ID,
-- time period grouping
dt.USA_FISCAL_YEAR_BEGIN_DT
) x
where denom is not null
But I'm getting a syntax error near 'sum' according to Oracle, and I'm missing a parenthesis according to MS SQL Server Management Studio. Do any of you beautiful internet people know what I'm doing wrong?

Missing comma between two columns and also select in sub-select
SELECT *
FROM (SELECT Sum(CASE -- select missing here
WHEN qm.SCIPINF1 = 'E'
AND qm.SCIPINF1_POPULATION_C = 7 THEN 1
ELSE 0
END) AS num, --comma missing here
Sum(CASE
WHEN qm.SCIPINF1 IN ( 'D', 'E' )
AND qm.SCIPINF1_POPULATION_C = 1 THEN 1
ELSE 0
END) AS denom, --comma missing here
-- summary level columns
cms.FACILITY_GROUP_ID,
-- time period columns
dt.USA_FISCAL_YEAR_BEGIN_DT

Related

Is there a way to collect the data and inspect in one pass using groupby function

Sample Data of table_1
Have this Query that returns
select
customer,
SUM(CASE WHEN activity IN ( 'a','b')
THEN 1
ELSE 0 END) AS num_activity_a_or_b
from table_1
group by customer
Results:
Want to extend this to return one more column if for a given code say X1 if the Activity is "a" and "c" then return num_of_a_and_c_activity.
A bit stuck how to collect and inpect the code and activities in one pass.
can we combine windowing function to achieve this.
Please advise and help
UPDATE:
based on the updated results, maybe the below query is what you need
So what i assume is that you need both a and c as well x1 .
So I count distinct activities which are a and c and then do integer division by 2. if only a is present then count distinct =1 but 1/2 =0 in integer division.
It is only 1 when both a and c are present.
select
customer,
SUM(CASE WHEN activity IN ( 'a','b')
THEN 1
ELSE 0
END) AS num_activity_a_or_b,
COUNT(DISTINCT CASE WHEN code IN ('x1') AND activity IN ( 'a','c')
THEN activity
ELSE NULL
END)/2 AS num_activity_a_and_c
from table_1
group by customer
Maybe your query can be
select
customer,
SUM(CASE WHEN activity IN ( 'a','b')
THEN 1
ELSE 0
END) AS num_activity_a_or_b,
SUM(CASE WHEN code IN ('x1') AND activity IN ( 'a','c')
THEN 1
ELSE 0
END) AS num_activity_a_or_c
from table_1
group by customer

Sum a column and perform more calculations on the result? [duplicate]

This question already has an answer here:
How to use an Alias in a Calculation for Another Field
(1 answer)
Closed 3 years ago.
In my query below I am counting occurrences in a table based on the Status column. I also want to perform calculations based on the counts I am returning. For example, let's say I want to add 100 to the Snoozed value... how do I do this? Below is what I thought would do it:
SELECT
pu.ID Id, pu.Name Name,
COUNT(*) LeadCount,
SUM(CASE WHEN Status = 'Working' THEN 1 ELSE 0 END) AS Working,
SUM(CASE WHEN Status = 'Uninterested' THEN 1 ELSE 0 END) AS Uninterested,
SUM(CASE WHEN Status = 'Converted' THEN 1 ELSE 0 END) AS Converted,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END) AS Snoozed,
Snoozed + 100 AS Test
FROM
Prospects p
INNER JOIN
ProspectsUsers pu on p.OwnerId = pu.SalesForceId
WHERE
p.Store = '108'
GROUP BY
pu.Name, pu.Id
ORDER BY
Name
I get this error:
Invalid column name 'Snoozed'.
How can I take the value of the previous SUM statement, add 100 to it, and return it as another column? What I was aiming for is an additional column labeled Test that has the Snooze count + 100.
You can't use one column to create another column in the same way that you are attempting. You have 2 options:
Do the full calculation (as #forpas has mentioned in the comments above)
Use a temp table or table variable to store the data, this way you can get the first 5 columns, and then you can add the last column or you can select from the temp table and do the last column calculations from there.
You can not use an alias as a column reference in the same query. The correct script is:
SELECT
pu.ID Id, pu.Name Name,
COUNT(*) LeadCount,
SUM(CASE WHEN Status = 'Working' THEN 1 ELSE 0 END) AS Working,
SUM(CASE WHEN Status = 'Uninterested' THEN 1 ELSE 0 END) AS Uninterested,
SUM(CASE WHEN Status = 'Converted' THEN 1 ELSE 0 END) AS Converted,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END)+100 AS Snoozed
FROM
Prospects p
INNER JOIN
ProspectsUsers pu on p.OwnerId = pu.SalesForceId
WHERE
p.Store = '108'
GROUP BY
pu.Name, pu.Id
ORDER BY
Name
MSSQL does not allow you to reference fields (or aliases) in the SELECT statement from within the same SELECT statement.
To work around this:
Use a CTE. Define the columns you want to select from in the CTE, and then select from them outside the CTE.
;WITH OurCte AS (
SELECT
5 + 5 - 3 AS OurInitialValue
)
SELECT
OurInitialValue / 2 AS OurFinalValue
FROM OurCte
Use a temp table. This is very similar in functionality to using a CTE, however, it does have different performance implications.
SELECT
5 + 5 - 3 AS OurInitialValue
INTO #OurTempTable
SELECT
OurInitialValue / 2 AS OurFinalValue
FROM #OurTempTable
Use a subquery. This tends to be more difficult to read than the above. I'm not certain what the advantage is to this - maybe someone in the comments can enlighten me.
SELECT
5 + 5 - 3 AS OurInitialValue
FROM (
SELECT
OurInitialValue / 2 AS OurFinalValue
) OurSubquery
Embed your calculations. opinion warning This is really sloppy, and not a great approach as you end up having to duplicate code, and can easily throw columns out-of-sync if you update the calculation in one location and not the other.
SELECT
5 + 5 - 3 AS OurInitialValue
, (5 + 5 - 3) / 2 AS OurFinalValue
You can't use a column alias in the same select. The column alias do not precedence / sequence; they are all created after the eval of the select result, just before group by and order by.
You must repeat code :
SELECT
pu.ID Id,pu.Name Name,
COUNT(*) LeadCount,
SUM(CASE WHEN Status = 'Working' THEN 1 ELSE 0 END) AS Working,
SUM(CASE WHEN Status = 'Uninterested' THEN 1 ELSE 0 END) AS Uninterested,
SUM(CASE WHEN Status = 'Converted' THEN 1 ELSE 0 END) AS Converted,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END) AS Snoozed,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END)+ 100 AS Test
FROM
Prospects p
INNER JOIN
ProspectsUsers pu on p.OwnerId = pu.SalesForceId
WHERE
p.Store = '108'
GROUP BY
pu.Name, pu.Id
ORDER BY
Name
If you don't want to repeat the code, use a subquery
SELECT
ID, Name, LeadCount, Working, Uninterested,Converted, Snoozed, Snoozed +100 AS test
FROM
(SELECT
pu.ID Id,pu.Name Name,
COUNT(*) LeadCount,
SUM(CASE WHEN Status = 'Working' THEN 1 ELSE 0 END) AS Working,
SUM(CASE WHEN Status = 'Uninterested' THEN 1 ELSE 0 END) AS Uninterested,
SUM(CASE WHEN Status = 'Converted' THEN 1 ELSE 0 END) AS Converted,
SUM(CASE WHEN SnoozedId > 0 THEN 1 ELSE 0 END) AS Snoozed
FROM Prospects p
INNER JOIN ProspectsUsers pu on p.OwnerId = pu.SalesForceId
WHERE p.Store = '108'
GROUP BY pu.Name, pu.Id) t
ORDER BY Name
or a view

SQL Server error simplify code due to multiple joins

I need an alternative way to simplify this code.
This code computes the age of the balances of the client depending on the repayment schedule of loan. The filters are 1-7 days, 8-30, 31-60 .... and so on until it reach 181 and above
with membersWithLoans as -- gets members with loan
(
select
a.memberid, a.loanid, a.loanamt, a.intamt
from
loanmst a
where
loandt <= '12/19/2016'
and status = 'O'
)
,selectPaymentToDate as -- gets payments of the members to date
(
select
b.loanid, sum(a.princollamt) as princollamt1,
sum(a.intcollamt) as intcollamt1
from
collectiondtl a
inner join
membersWithLoans b on a.loanid = b.loanid
where
a.accdate <= '12/19/2016'
group by
b.loanid)
,selectBalanceToDate as -- gets the balance of member to date
(
select
b.loanid,
sum(a.princeamt) as prinBalanceToDate,
sum(a.instamt) as intBalanceToDate,
sum(a.insamt) as insuBalanceToDate
from
loandtl a
inner join
membersWithLoans b on a.loanid = b.loanid
where
a.duedt <= '12/19/2016'
group by
b.loanid)
, combineBalanceWithpayment as -- combine payment and balance
(
select a.loanid,a.loanamt, a.intamt,
(case
when b.prinBalanceToDate is null then 0
else b.prinBalanceToDate end) as prinBalanceToDate2,
(case
when b.intBalanceToDate is null then 0
else b.intBalanceToDate end) as intBalanceToDate2,
(case
when b.insuBalanceToDate is null then 0
else b.insuBalanceToDate end) as insuBalanceToDate2,
(case
when c.princollamt1 is null then 0
else c.princollamt1 end) as PrincipalCollectiontoDate,
(case
when c.intcollamt1 is null then 0
else c.intcollamt1 end) as IntCollectiontoDate,
cast(((case
when b.prinBalanceToDate is null then 0
else b.prinBalanceToDate
end)
-
(case
when c.princollamt1 is null then 0
else c.princollamt1 end))as decimal(10,2)) as Arrears
from
membersWithLoans a
left join selectBalanceToDate b
on a.loanid=b.loanid
left join selectPaymentToDate c
on a.loanid=c.loanid
)
,filterNegativeArrears as
(
select *
from
combineBalanceWithpayment
where Arrears > 0
)
the code above gets the member information
,select1To7days as -- this code gets amount to be paid in a specific schedule
(
select b.loanid,
sum((case
when a.princeamt is null then 0
else a.princeamt end))as prin7Daysbalance
from loandtl a
inner join membersWithLoans b
on a.loanid=b.loanid
where
a.duedt > DATEADD(day,-7,'12/19/2016')
and
a.duedt<='12/19/2016'
group by b.loanid
)
,select8to30days as -- this code gets amount to be paid in a specific schedule
(
select b.loanid,
sum((case
when a.princeamt is null then 0
else a.princeamt end))as prin8To30Daysbalance
from loandtl a
inner join membersWithLoans b
on a.loanid=b.loanid
where
a.duedt<=DATEADD(day,-7,'12/19/2016')
and a.duedt > DATEADD(day,-30,'12/19/2016')
group by b.loanid
)
-- and so on ..... the filters for schedule is compose of 31 to 60days, 61 to 90 days,
--121 to 180 days, 181 and above. there is no pattern since it the requirement on days may change
, computePar1To7days as -- computes the 1 to 7 days
(
select a.loanid, cast((a.arrears - a.Par1To7days) as decimal(10,2)) as deductedArrears, a.Par1To7days
from
(
select a.loanid,a.arrears,
cast((case
when a.arrears >= b.prin7Daysbalance then b.prin7Daysbalance -- if the arrears is greater than the 7days balance to be collected then it will be show
else a.arrears end)as decimal(10,2))as Par1To7days -- else the remaining is the arrears
from
filterNegativeArrears a
left join select1To7days b
on a.loanid=b.loanid
) a
where cast((a.arrears - a.Par1To7days) as decimal(10,2)) > 0
)
,computePar8To30days as -- computes the 8 to 30 days
(
select a.loanid, cast((a.arrears - a.Par8To30days)as decimal(10,2)) as deductedArrears, a.Par8To30days
from
(
select a.loanid, a.deductedArrears as arrears,
cast((case
when (a.deductedArrears) > 0
then
(case
when (a.deductedArrears)>= b.prin8To30Daysbalance
then b.prin8To30Daysbalance
else (a.deductedArrears)
end)
else 0 end)as decimal(10,2))as Par8To30days
from computePar1To7days a
left join select8To30days b
on a.loanid=b.loanid
) a
where cast((a.arrears - a.Par8To30days) as decimal(10,2)) > 0
)
-- so on until all par is computed. 31 to 60 days, 61 to 90 days,
--121 to 180 days, 181 and above. there is no pattern since it the requirement on days may change
the code above gets the sum of data from specific schedules like
1 to 7 days, 8-30 days, 31 to 60 days, 61 to 90 days, 121 to 180 days, 181 and above
select a.*,
b.Par1To7days,
c.Par8To30days,
d.Par31To60days,
e.Par61To90days,
f.Par91To120days,
g.Par121To180days --,
--h.Par181AndAbovedays
from
filterNegativeArrears a
left join computePar1To7days b
on a.loanid=b.loanid
left join computePar8To30days c
on a.loanid=c.loanid
left join computePar31To60days d
on a.loanid=d.loanid
left join computePar61To90days e
on a.loanid=e.loanid
left join computePar91To120days f
on a.loanid=f.loanid
left join computePar121To180days g
on a.loanid=g.loanid
--left join computePar181AndAbovedays h
-- on a.loanid=h.loanid
the code above joins the computed age
The code is working fine and calculating fine
but when I add more join in the selection I get an error
left join computePar181AndAbovedays h
on a.loanid=h.loanid
The problem is I started encountering the error:
An expression services limit has been reached. Please look for
potentially complex expressions in your query, and try to simplify
them.
I still need more table to join with my query.
Can you suggest ways to simplify this query is highly appreciated
You are obviously running into a limit there and budging that limit will not be possible with the query you have. Follow the advice given in the error message: simplify.
How? Well you have a multitude of CTE's defined. Another way of writing your query is by materializing the CTE's in temporary tables before the actual query and then using the temporary tables instead.
For example, this CTE:
membersWithLoans as -- gets members with loan
(
select a.memberid, a.loanid,a.loanamt,a.intamt
from loanmst a
where loandt<='12/19/2016'
and status = 'O'
)
Can be be materialized to a temporary table:
select a.memberid, a.loanid,a.loanamt,a.intamt
into #membersWithLoans
from loanmst a
where loandt<='12/19/2016'
and status = 'O'
This will create a temporary table #membersWithLoans that can be used in further temporary table creations or in your final query.
To illustrate further, suppose you have materialized all your CTE's to temporary tables, you would have no more WITH clause. You would then finally use the temporary tables in your final SELECT query:
-- create all temporary tables (one of them being #filterNegativeArrears)
select
a.*,
-- the rest of your selections
from
#filterNegativeArrears a
-- the rest of the joined temporary tables
-- the rest of your query (WHERE, ORDER BY etc)

Not a GROUP BY Expression & aggregate functions

I was wondering why, for this query that I have right here, why I have to use the MAX() aggregate function for the case statements, and not just jump directly into the case statement:
select
bank_id,
tran_branch_code,
acct_sol_id,
acct_sol_name,
transaction_date,
gl_date,
transaction_id,
account_number,
max(case
when cast(substr(GLSH_Code,0,1) as int) >= 1
and cast(substr(GLSH_Code,0,1) as int) <= 5
and trans_type = 'D'
then (trans_amount)
--else 0
end ) Ind_Part_Tran_Dr_RBU,
max(case
when cast(substr(GLSH_Code,0,1) as int) >= 1
and cast(substr(GLSH_Code,0,1) as int) <= 5
and trans_type = 'C'
then (trans_amount)
--else 0
end) Ind_Part_Tran_Cr_RBU,
max(case
when cast(substr(GLSH_Code,0,1) as int) = 0
or (cast(substr(GLSH_Code,0,1) as int) >= 6
and cast(substr(GLSH_Code,0,1) as int) <= 9)
and trans_type = 'D'
then (trans_amount)
--else 0
end)Ind_Part_Tran_Dr_FCDU,
max(case
when cast(substr(GLSH_Code,0,1) as int) = 0
or (cast(substr(GLSH_Code,0,1) as int) >= 6
and cast(substr(GLSH_Code,0,1) as int) <= 9)
and trans_type = 'C'
then (trans_amount)
--else 0
end) Ind_Part_Tran_Cr_FCDU,
ccy_alias,
ccy_name,
acct_currency,
tran_currency
from
(
SELECT
DTD.BANK_ID,
DTD.SOL_ID Acct_Sol_ID, --Account Sol ID
dtd.br_code Tran_branch_code, -- branch code of the transacting branch
sol.sol_desc Acct_sol_name, -- name/description of SOL
DTD.TRAN_DATE Transaction_Date, --TransactionDate
DTD.GL_DATE GL_Date, --GL Date
TRIM(DTD.TRAN_ID) Transaction_ID, --Transaction ID
DTD.GL_SUB_HEAD_CODE GLSH_Code, --GLSH Code
dtd.tran_amt trans_amount,
GAM.ACCT_CRNCY_CODE Acct_Currency, --Account Currency
DTD.TRAN_CRNCY_CODE Tran_Currency, --Transaction Currency
cnc.crncy_alias_num ccy_alias,
cnc.crncy_name ccy_name,
GAM.FORACID Account_Number, --Account Number
DTD.TRAN_PARTICULAR Transaction_Particulars, --Transaction Particulars
DTD.CRNCY_CODE DTD_CCY,
--GSH.CRNCY_CODE GSH_CCY,
DTD.PART_TRAN_TYPE Transaction_Code,
--'Closing_Balance',
DTD.PSTD_USER_ID PostedBy,
CASE WHEN DTD.REVERSAL_DATE IS NOT NULL
THEN 'Y' ELSE 'N' END Reversal,
TRIM(DTD.TRAN_ID) REV_ORIG_TRAN_ID,
--OTT.REF_NUM OAP_REF_NUM,
'OAP_SETTLEMENT',
'RATE_CODE',
EAB.EOD_DATE
FROM TBAADM.DTD
LEFT OUTER JOIN TBAADM.GAM ON DTD.ACID = GAM.ACID AND DTD.BANK_ID = GAM.BANK_ID
LEFT OUTER JOIN TBAADM.EAB ON DTD.ACID = EAB.ACID AND DTD.BANK_ID = EAB.BANK_ID AND EAB.EOD_DATE = '24-MAR-2014'
left outer join tbaadm.sol on dtd.sol_id = sol.sol_id and dtd.bank_id = sol.bank_id
left outer join tbaadm.cnc on dtd.tran_crncy_code = cnc.crncy_code
WHERE DTD.BANK_ID = 'CBC01'
AND GAM.ACCT_OWNERSHIP = 'O'
AND GAM.DEL_FLG != 'Y'
--AND DTD.TRAN_DATE = '14-APR-2014'
AND DTD.TRAN_DATE between '01-APR-2014' and '21-APR-2014'
--and foracid in ('50010112441109','50010161635051')
--and DTD.SOL_ID = '5001'
and GAM.ACCT_CRNCY_CODE = 'USD'
)
group by
bank_id,
tran_branch_code,
acct_sol_id,
acct_sol_name,
transaction_date,
gl_date,
transaction_id,
account_number,
ccy_alias,
ccy_name,
Acct_Currency,
Tran_Currency
Because If I would remove the MAX(), I'd get the "Not a GROUP BY Expression", and Toad points me to the first occurrence of the GLSH_Code. Based from other websites, the cure for this is really adding the MAX() function. I would just like to understand why should I use that particular function, what it exactly does in the query, stuff like that.
EDIT: inserted the rest of the code.
I know for sure what MAX() does, it returns the largest value in an expression. But in this case, I can't seem to figure out exactly what that largest value is that the function is attempting to return.
The GROUP BY statement declares that all columns returned in the SELECT should be aggregated, but that you want to separate the results by those listed in the GROUP BY.
This means we have to use aggregate functions like MIN, MAX, AVG, SUM, etc. on any column that is NOT listed in the GROUP BY.
It's about telling the SQL engine what the expected results should be when there is more than one option.
In a simple example, we have a table with three columns:
PrimaryId SubId RowValue
1 1 1
2 1 2
3 2 4
4 2 8
And an SQL like the following (which is invalid):
SELECT SubId, RowValue
FROM SampleTable
GROUP BY SubId
We know we want the distinct SubId's (because of the GROUP BY), but we don't know what RowValue should be when we aggregate the results.
SubId RowValue
1 ?
2 ?
We have to be explicit in our query, and indicate what RowValue should be as the results can vary.
If we choose MIN(RowValue) we see:
SubId RowValue
1 1
2 4
If we choose MAX(RowValue) we see:
SubId RowValue
1 2
2 8
If we choose SUM(RowValue) we see:
SubId RowValue
1 3
2 12
Without being explicit there's a high likelihood that the results will be wrong, so our SQL engine of choice protects us from ourselves by enforcing the need for aggregate functions.
You have group by clause at the end on all the columns except for Ind_Part_Tran_Dr_RBU, Ind_Part_Tran_Cr_RBU, Ind_Part_Tran_Dr_FCDU, Ind_Part_Tran_Cr_FCDU. In this case oracle wants you to tell what to do with these columns, i.e. based on which function it has to aggregate them for every group it finds.

Counting all other types but the current one

I'm trying to write this query, that would calculate the average value of all the columns except the one that contains the type value, which I'm grouping the whole query by.
So for 4 types for example, each column in the resulting table will contain the average of all the other three type's values, i need to exclude the current type's rows.
As an example, if I was to calculate each type's average value for itself, the query would look like:
SELECT
SUM(some value) / COUNT(TYPE)
FROM TEMPTABLE
GROUP BY TYPE
Now I'm trying to calculate the other three's total average. Thanks.
You can do one query to get the distinct types, and LEFT JOIN the same table, checking for type-inequality:
SELECT t1.type,
SUM(t2.some_value) / COUNT(t2.type)
FROM ( SELECT DISTINCT type FROM temptable ) t1
LEFT JOIN temptable t2 ON ( t1.type <> t2.type )
GROUP BY t1.type
Since you only want the average, you could replace the line
FROM ( SELECT DISTINCT type FROM temptable ) t1
by
FROM temptable t1
but the first solution might perform better, since the number of rows is reduced earlier.
The starting point here is to make a cartesian join between your types and your temptable (guessing your tables structure is : type(id, type), valueTable(id, type_id, some_value))
The following query
SELECT t.type, SUM(vt.someValue) /
COUNT (*) AS sum FROM type t,
valueTable vt WHERE vt.type_id != t.id
GROUP BY t.type
should do the trick.
Will this do what you need?
(Possibly with another CASE statement to avoid divide by zero errors if there is a possibility none of a type might be returned, I've also not explicitly accounted for the case that type is NULL)
SELECT
SUM(CASE WHEN TYPE <> 'Type1' THEN someValue ELSE 0 END) /
SUM(CASE WHEN TYPE = 'Type1' THEN 1 ELSE 0 END) AS T1,
SUM(CASE WHEN TYPE <> 'Type2' THEN someValue ELSE 0 END) /
SUM(CASE WHEN TYPE = 'Type2' THEN 1 ELSE 0 END) AS T2,
SUM(CASE WHEN TYPE <> 'Type3' THEN someValue ELSE 0 END) /
SUM(CASE WHEN TYPE = 'Type3' THEN 1 ELSE 0 END) AS T3,
SUM(CASE WHEN TYPE <> 'Type4' THEN someValue ELSE 0 END) /
SUM(CASE WHEN TYPE = 'Type4' THEN 1 ELSE 0 END) AS T4
FROM TEMPTABLE
I think that you can just use this:
SELECT type, avg(col_01)
FROM myTable
GROUP BY type
Should work on Sybase too:
SELECT
SUM(some value) / SUM(CASE WHEN TYPE = 1 THEN 1 ELSE 0 END)
FROM TEMPTABLE
GROUP BY TYPE