Group BY Expression column - sql

we're trying to make our table add together all values in column 2 (QtyComp - an expression column of qtyorder * totalqty basically), where they have the same ItemNo (column 1).
So, we currently get the below:
ItemNo QtyCom
7441 3
7441 1
7441 5
What we want is it to return this:
ItemNo QtyCom
7441 9
Our code is below; I've bolded the part that we need it to sum the results of:
SELECT TOP (100) PERCENT ItemSpecs_2.itemno,
workorderdetails.qtycomplete *
ItemSpecFullStruc_2.totalqtyperroot AS QtyComp
FROM dbo.workorderdetails AS WorkOrderDetails
INNER JOIN dbo.itemspecfullstruc AS ItemSpecFullStruc_2
ON ItemSpecFullStruc_2.rootitemspecid =
workorderdetails.itemspecid
INNER JOIN dbo.itemspecs AS ItemSpecs_2
ON ItemSpecs_2.itemspecid = ItemSpecFullStruc_2.childitemspecid
INNER JOIN dbo.workorder AS WorkOrder_1
ON WorkOrder_1.workorderid = workorderdetails.workorderid
LEFT OUTER JOIN dbo.tobescheduled_completed
ON WorkOrder_1.workorderid =
dbo.tobescheduled_completed.workorderid
WHERE ( workorderdetails.completed = 1 )
AND ( workorderdetails.compdate > Getdate() - 42 )
GROUP BY ItemSpecs_2.itemno,
workorderdetails.qtyordered,
ItemSpecFullStruc_2.totalqtyperroot,
workorderdetails.[lineno],
workorderdetails.qtycomplete,
workorderdetails.compdate,
workorderdetails.qtycomplete * ItemSpecFullStruc_2.totalqtyperroot
We would really appreciate some ideas!
Thanks,
Trish

Try this
SELECT TOP (100) PERCENT ItemSpecs_2.itemno,
sum(workorderdetails.qtycomplete *
ItemSpecFullStruc_2.totalqtyperroot) AS QtyComp
FROM dbo.workorderdetails AS WorkOrderDetails
INNER JOIN dbo.itemspecfullstruc AS ItemSpecFullStruc_2
ON ItemSpecFullStruc_2.rootitemspecid =
workorderdetails.itemspecid
INNER JOIN dbo.itemspecs AS ItemSpecs_2
ON ItemSpecs_2.itemspecid = ItemSpecFullStruc_2.childitemspecid
INNER JOIN dbo.workorder AS WorkOrder_1
ON WorkOrder_1.workorderid = workorderdetails.workorderid
LEFT OUTER JOIN dbo.tobescheduled_completed
ON WorkOrder_1.workorderid =
dbo.tobescheduled_completed.workorderid
WHERE ( workorderdetails.completed = 1 )
AND ( workorderdetails.compdate > Getdate() - 42 )
GROUP BY ItemSpecs_2.itemno,
workorderdetails.qtyordered,
ItemSpecFullStruc_2.totalqtyperroot,
workorderdetails.[lineno],
workorderdetails.qtycomplete,
workorderdetails.compdate

Once you will use top for select statement, you need to use order by. you can try the following query.
SELECT TOP(100) PERCENT A.itemno,SUM(QtyComp) FROM
(SELECT ItemSpecs_2.itemno,
(workorderdetails.qtycomplete *
ItemSpecFullStruc_2.totalqtyperroot) AS QtyComp
FROM dbo.workorderdetails AS WorkOrderDetails
INNER JOIN dbo.itemspecfullstruc AS ItemSpecFullStruc_2
ON ItemSpecFullStruc_2.rootitemspecid =
workorderdetails.itemspecid
INNER JOIN dbo.itemspecs AS ItemSpecs_2
ON ItemSpecs_2.itemspecid = ItemSpecFullStruc_2.childitemspecid
INNER JOIN dbo.workorder AS WorkOrder_1
ON WorkOrder_1.workorderid = workorderdetails.workorderid
LEFT OUTER JOIN dbo.tobescheduled_completed
ON WorkOrder_1.workorderid =
dbo.tobescheduled_completed.workorderid
WHERE ( workorderdetails.completed = 1 )
AND ( workorderdetails.compdate > Getdate() - 42 ) ) A
GROUP BY A.itemno
ORDER BY A.itemno
Thanks

SELECT SUM(QTYCOM) OVER (PARTITION BY ITEMNO)
FROM
...

Related

Select max column from joined tables

The joined tables will result as a view like below. I wish to select just 1 record of the max id or prod_month column.
con_model srt_value_current con_id prod_month id
model 4 49 37 45145
model 4 49 38 45726
SELECT DISTINCT TOP (100) PERCENT dbo.DM_TBL_CONFIGURATION_MODEL.con_model, dbo.SRT_Data.SRT_VALUE_CURRENT, dbo.DM_TBL_CONFIGURATION_MODEL.con_id, dbo.SRT_Data.ID, dbo.SRT_Data.PROD_MONTH
FROM dbo.DM_TBL_CONFIGURATION_MODEL LEFT OUTER JOIN
dbo.SRT_ItemNumbers ON dbo.DM_TBL_CONFIGURATION_MODEL.con_model = dbo.SRT_ItemNumbers.ITEM_NUMBER LEFT OUTER JOIN
dbo.SRT_Data ON dbo.SRT_ItemNumbers.ID = dbo.SRT_Data.ITEM_NUMBER_ID
WHERE (SRT_Data.id) IN
( SELECT MAX(id)
FROM SRT_Data
)
and con_model='model'
If you want one row, use TOP (1):
SELECT TOP (1) cm.con_model, s.SRT_VALUE_CURRENT, cm.con_id, s.ID, s.PROD_MONTH
FROM dbo.DM_TBL_CONFIGURATION_MODEL cm LEFT OUTER JOIN
dbo.SRT_ItemNumbers i
ON cmL.con_model = i.ITEM_NUMBER LEFT OUTER JOIN
dbo.SRT_Data s
ON i.ID = s.ITEM_NUMBER_ID
WHERE cm.con_model = 'model'
ORDER BY s.prod_month DESC;
I am using Cross Apply.
SELECT *
FROM dbo.DM_TBL_CONFIGURATION_MODEL a CROSS APPLY
(
Select Top 1 b.ID,dbo.SRT_Data.SRT_VALUE_CURRENT
From dbo.SRT_ItemNumbers b LEFT OUTER JOIN
dbo.SRT_Data ON b.ID = dbo.SRT_Data.ITEM_NUMBER_ID
Where b.ITEM_NUMBER = a.con_model
Order By ID Desc
) X

trying to modifying a multi join query with issues

I have a simplified query shown below, that does mulitple joins. I'm trying to add a field to be selected but I am unable to find a good way of joining it without changing the number of records that come up...
SELECT tblApp.AppID
,'Type' = tblRef.Label
,'Status' = tblRef2.Label
FROM (
(
(
tblApp LEFT JOIN tblAppExt ON tblApp.AppID = tblAppExt.AppID
) LEFT JOIN tblRef ON tblApp.AppTypeID = tblReferenceData.ID
) LEFT JOIN tblRef tblRef2 ON tblApp.AppStatusID = tblRef2.ID
)
As is - I'm getting 149 results, if I try to Join it in any way, I get like 10 time fold the number of records. All I'm hoping to do is be able to SELECt another field. I'm hoping to join tblAppExt2 that has AppID just like the other tables in the FROM part of the query, so my goal would basically be to do this:
SELECT tblApp.AppID
,'Type' = tblRef.Label
,'Status' = tblRef2.Label
,'NewField' = tblAppExt2.NewField
First thing to try is DISTINCT:
SELECT DISTINCT
tblApp.AppID
, [Type] = tblRef.Label
, [Status] = tblRef2.Label
, [NewField] = tblAppExt2.NewField
FROM tblApp
LEFT JOIN tblAppExt
ON tblApp.AppID = tblAppExt.AppID
LEFT JOIN tblRef
ON tblApp.AppTypeID = tblReferenceData.ID
LEFT JOIN tblRef tblRef2
ON tblApp.AppStatusID = tblRef2.ID
LEFT JOIN tblAppExt2.NewField
ON something = somethingElse ;
If that doesn't work, it means there are multiple different values for [NewField] and you'll need to tell it how to select the correct one. For example, to take the most recent [NewField] you can use a CTE with the ROW_NUMBER function:
; WITH AllRecords
AS (
SELECT DISTINCT
tblApp.AppID
, [Type] = tblRef.Label
, [Status] = tblRef2.Label
, [NewField] = tblAppExt2.NewField
, MyRank = ROW_NUMBER() OVER(PARTITION BY tblApp.ID ORDER BY tblAppExt2.DateEntered DESC)
FROM tblApp
LEFT JOIN tblAppExt
ON tblApp.AppID = tblAppExt.AppID
LEFT JOIN tblRef
ON tblApp.AppTypeID = tblReferenceData.ID
LEFT JOIN tblRef tblRef2
ON tblApp.AppStatusID = tblRef2.ID
LEFT JOIN tblAppExt2.NewField
ON something = somethingElse
)
SELECT *
FROM AllRecords
WHERE AllRecords.MyRank = 1 ;
You can use outer apply or correlated subquery :
SELECT tblApp.AppID, tblRef.Label as [Type], tblRef2.Label as [Status],
tappext.NewField
FROM tblApp tapp LEFT JOIN
tblAppExt tex
ON tapp.AppID = tex.AppID LEFT JOIN
tblRef tref
ON tapp.AppTypeID = tref.ID LEFT JOIN
tblRef tblRef2
ON tapp.AppStatusID = tblRef2.ID OUTER APPLY
( SELECT TOP (1) tappext.*
FROM tblAppExt2 tappext
WHERE tapp.AppID = AppID
ORDER BY ??
) tappext;

SQL Server rows count return with inner join more than once in same table

I have this code
select
count(cat_item_tb.item_id),
count(t.item_id)
from
cat_tb
inner join
item_tb on cat_tb.cat_id = item_tb.cat_id
inner join
cat_item_tb on item_tb.item_id = cat_item_tb.item_id and t.ss = 0
inner join
cat_item_tb t on item_tb.item_id = t.item_id and t.ss = 1
All I need to return value without duplicate. In past code it must return 7 in every count but it's return 49 the two count() affected each other. I use distinct but it does not return the correct count, because there is (item_id) more than once in table
Thank you so much
Seems to me that you need to count distinct, to count the unique values
...
count(DISTINCT cat_item_tb.item_id)
...
The 2 counts in your query will be the same. That's simply because you INNER JOIN on those item_id's. So they will be identical by defenition.
If I understand correctly the task, you could use groub by to get desired results
select count(cat_item_tb.item_id), cat_item_tb.ss
from cat_tb
inner join item_tb on cat_tb.cat_id = item_tb.cat_id
inner join cat_item_tb on item_tb.item_id = cat_item_tb.item_id
where t.ss = 0 or t.ss = 1
group by cat_item_tb.ss
The query will return 2 rows with count values in first column.
More info about group by is here link
I believe you wanted to write something like:
select
count(c1.item_id),
count(c2.item_id)
from
cat_tb as a
inner join item_tb as b on ( a.cat_id = b.cat_id )
inner join cat_item_tb as c1 on ( b.item_id = c1.item_id ) and ( c1.ss = 0 )
inner join cat_item_tb as c2 on ( b.item_id = c2.item_id ) and ( c2.ss = 1 )
This won't work because of the inner joins. If the first join of c1 returns 3 rows and the second join of c2 returns 4 rows, you end up with count = 3*4
Try this:
;with cte1 as (
select
b.item_id,
'c1_count' = count( c1.item_id )
from
item_tb as b
left join cat_item_tb as c1 on ( b.item_id = c1.item_id ) and ( c1.ss = 0 )
group by
b.item_id
),
cte2 as (
select
b.item_id,
'c2_count' = count(c2.item_id)
from
item_tb as b
left join cat_item_tb as c2 on ( b.item_id = c2.item_id ) and ( c2.ss = 1 )
group by
b.item_id
)
select
a.item_id, a.c1_count, b.c2_count
from
cte1 as a
inner join cte2 as b on ( b.item_id = a.item_id )
For performance reasons you could replace the left join in ctes with inner join ONLY if you are sure that there are rows in cat_item_tb with item_id and all of them has the ss column set to 0 or 1.

Alternate way of Exists with Having clause

The below query is to retrieve the records whose (SGT_DISBURSEMENT_REQUEST) count is only one. It is working great. But performance wise it didn't took so much of time since we have 100 000 records.
Is there any better way to do it?
SELECT PA.PERSON_ID,
PA.PERSON_ACCOUNT_ID,
DR.DISBURSEMENT_REQUEST_ID,
SUM
(
ISNULL(CD.EE_PRE_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_PRE_TAX_AMT,0)
) AS EE_PRE_TAX_CONTRIB,
DD.PRE_TAX_AMOUNT AS DISB_DTL_PRE_TAX_AMOUNT,
SUM
( ISNULL(CD.EE_POST_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_POST_TAX_AMT,0)
) AS EE_POST_TAX_CONTRIB,
DD.POST_TAX_AMOUNT AS DISB_DTL_POST_TAX_AMOUNT
FROM SGT_DISBURSEMENT_REQUEST DR
INNER JOIN SGT_DISBURSEMENT_DETAIL DD ON DR.DISBURSEMENT_REQUEST_ID = DD.DISBURSEMENT_REQUEST_ID
INNER JOIN SGT_PERSON_ACCOUNT PA ON PA.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID
INNER JOIN SGT_CONTRIB_DTL CD ON CD.PERSON_ACCOUNT_ID = PA.PERSON_ACCOUNT_ID
WHERE DR.REQUEST_CATEGORY_VALUE = 'REFD' AND
DD.DETAIL_CATEGORY_VALUE = 'REFD' AND
CD.STATUS_VALUE = 'VALD' AND
CD.POSTED_DATE <= DR.ACCEPTED_TO_PAYROLL_DATE AND
DR.DISBURSEMENT_STATUS_VALUE <> 'CANL' AND
EXISTS
(
SELECT 1 FROM SGT_DISBURSEMENT_REQUEST SDR1
INNER JOIN SGT_DISBURSEMENT_DETAIL SDD1 ON SDD1.DISBURSEMENT_REQUEST_ID = SDR1.DISBURSEMENT_REQUEST_ID
WHERE SDR1.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID and SDD1.DETAIL_CATEGORY_VALUE = DD.DETAIL_CATEGORY_VALUE
GROUP BY SDR1.PERSON_ACCOUNT_ID
HAVING COUNT(*) = 1
)
GROUP BY
PA.PERSON_ID, PA.PERSON_ACCOUNT_ID, DR.DISBURSEMENT_REQUEST_ID, DD.PRE_TAX_AMOUNT, DD.POST_TAX_AMOUNT
For Performance improvement you can have the Filter Conditions in the Join Clause, instead of where clause. In this case each join will restrict the results to even lesser number of rows.
SELECT PA.PERSON_ID,
PA.PERSON_ACCOUNT_ID,
DR.DISBURSEMENT_REQUEST_ID,
SUM
(
ISNULL(CD.EE_PRE_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_PRE_TAX_AMT,0)
) AS EE_PRE_TAX_CONTRIB,
DD.PRE_TAX_AMOUNT AS DISB_DTL_PRE_TAX_AMOUNT,
SUM
( ISNULL(CD.EE_POST_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_POST_TAX_AMT,0)
) AS EE_POST_TAX_CONTRIB,
DD.POST_TAX_AMOUNT AS DISB_DTL_POST_TAX_AMOUNT
FROM SGT_DISBURSEMENT_REQUEST DR
INNER JOIN SGT_DISBURSEMENT_DETAIL DD ON DR.DISBURSEMENT_REQUEST_ID = DD.DISBURSEMENT_REQUEST_ID AND DR.REQUEST_CATEGORY_VALUE = 'REFD' AND
DD.DETAIL_CATEGORY_VALUE = 'REFD' AND DR.DISBURSEMENT_STATUS_VALUE <> 'CANL'
INNER JOIN SGT_PERSON_ACCOUNT PA ON PA.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID
INNER JOIN SGT_CONTRIB_DTL CD ON CD.PERSON_ACCOUNT_ID = PA.PERSON_ACCOUNT_ID AND CD.STATUS_VALUE = 'VALD' AND
CD.POSTED_DATE <= DR.ACCEPTED_TO_PAYROLL_DATE
WHERE EXISTS
(
SELECT 1 FROM SGT_DISBURSEMENT_REQUEST SDR1
INNER JOIN SGT_DISBURSEMENT_DETAIL SDD1 ON SDD1.DISBURSEMENT_REQUEST_ID = SDR1.DISBURSEMENT_REQUEST_ID
WHERE SDR1.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID and SDD1.DETAIL_CATEGORY_VALUE = DD.DETAIL_CATEGORY_VALUE
GROUP BY SDR1.PERSON_ACCOUNT_ID
HAVING COUNT(*) = 1
)
GROUP BY
PA.PERSON_ID, PA.PERSON_ACCOUNT_ID, DR.DISBURSEMENT_REQUEST_ID, DD.PRE_TAX_AMOUNT, DD.POST_TAX_AMOUNT
if you use count over it should give you the same result and be better for performance:
select * from (
SELECT PA.PERSON_ID,
PA.PERSON_ACCOUNT_ID,
DR.DISBURSEMENT_REQUEST_ID,
SUM
(
ISNULL(CD.EE_PRE_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_PRE_TAX_AMT,0)
) AS EE_PRE_TAX_CONTRIB,
DD.PRE_TAX_AMOUNT AS DISB_DTL_PRE_TAX_AMOUNT,
SUM
( ISNULL(CD.EE_POST_TAX_AMT,0) +
ISNULL(CD.EE_ADDL_POST_TAX_AMT,0)
) AS EE_POST_TAX_CONTRIB,
DD.POST_TAX_AMOUNT AS DISB_DTL_POST_TAX_AMOUNT
,count(*) over(partition by PA.PERSON_ACCOUNT_ID ) as ct
FROM SGT_DISBURSEMENT_REQUEST DR
INNER JOIN SGT_DISBURSEMENT_DETAIL DD ON DR.DISBURSEMENT_REQUEST_ID = DD.DISBURSEMENT_REQUEST_ID
INNER JOIN SGT_PERSON_ACCOUNT PA ON PA.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID
INNER JOIN SGT_CONTRIB_DTL CD ON CD.PERSON_ACCOUNT_ID = PA.PERSON_ACCOUNT_ID
WHERE DR.REQUEST_CATEGORY_VALUE = 'REFD' AND
DD.DETAIL_CATEGORY_VALUE = 'REFD' AND
CD.STATUS_VALUE = 'VALD' AND
CD.POSTED_DATE <= DR.ACCEPTED_TO_PAYROLL_DATE AND
DR.DISBURSEMENT_STATUS_VALUE <> 'CANL'
GROUP BY
PA.PERSON_ID, PA.PERSON_ACCOUNT_ID, DR.DISBURSEMENT_REQUEST_ID, DD.PRE_TAX_AMOUNT, DD.PRE_TAX_AMOUNT, DD.POST_TAX_AMOUNT
) as x
where x.ct = 1
I would materialize this to a #temp
SELECT DR1.PERSON_ACCOUNT_ID, SDD1.DETAIL_CATEGORY_VALUE
FROM SGT_DISBURSEMENT_REQUEST SDR1
JOIN SGT_DISBURSEMENT_DETAIL SDD1
ON SDD1.DISBURSEMENT_REQUEST_ID = SDR1.DISBURSEMENT_REQUEST_ID
GROUP BY SDR1.PERSON_ACCOUNT_ID, SDD1.DETAIL_CATEGORY_VALUE
HAVING COUNT(*) = 1
join #temp
on #temp.PERSON_ACCOUNT_ID = DR.PERSON_ACCOUNT_ID
and #temp.DETAIL_CATEGORY_VALUE = DD.DETAIL_CATEGORY_VALUE

Sum record data into one

I have this query which returns qty in each of my branch. now the branch has two WH_subType as you see in the attached diagram i have attached. I want to sum the 2 subtype and show its available qty. how can i do it.
my select query is like this
SELECT
dbo.WarehouseType.name AS Section,
dbo.WarehouseSubType.name AS WH_Type,
dbo.WarehouseSubType1.name AS WH_SubType,
dbo.Branch.name AS Branch,
(dbo.WarehouseProductQuantity.actualQuantity - dbo.WarehouseProductQuantity.reservedQuantity) AS AvailQty,
dbo.WarehouseProductQuantity.tafsilId AS Tafsil,
dbo.Tafsil.description AS Product_Name
FROM
dbo.WarehouseSubType
INNER JOIN
dbo.WarehouseType
ON
(
dbo.WarehouseSubType.warehouseTypeId = dbo.WarehouseType.id)
INNER JOIN
dbo.WarehouseSubType1
ON
(
dbo.WarehouseSubType.id = dbo.WarehouseSubType1.warehouseSubTypeId)
INNER JOIN
dbo.Warehouse
ON
(
dbo.WarehouseSubType1.id = dbo.Warehouse.warehouseSubType1Id)
INNER JOIN
dbo.Branch
ON
(
dbo.Warehouse.branchId = dbo.Branch.id)
INNER JOIN
dbo.WarehouseProductQuantity
ON
(
dbo.Warehouse.id = dbo.WarehouseProductQuantity.warehouseId)
INNER JOIN
dbo.TafsilLink
ON
(
dbo.WarehouseProductQuantity.tafsilId = dbo.TafsilLink.sourceId)
INNER JOIN
dbo.Tafsil
ON
(
dbo.TafsilLink.targetId = dbo.Tafsil.id)
INNER JOIN
dbo.FinishProduct
ON
(
dbo.Tafsil.id = dbo.FinishProduct.tafsilId)
INNER JOIN
dbo.Supplier
ON
(
dbo.FinishProduct.supplierId = dbo.Supplier.tafsilId)
WHERE
WarehouseSubType1.warehouseSubTypeId IN (1,4)
group by dbo.WarehouseProductQuantity.tafsilId
Have you tried a group by
SELECT SubType, SUM(qty) AS QtySum
GROUP BY SubType
Every grouped by column should be in your select. Note: for every column you group by it further sub divides the data
Update based on OP comment:
If you want other columns you need to do something like
SELECT s.WH_SubType,s.AvailQty, t.other_cols
from
(SELECT
dbo.WarehouseSubType1.name AS WH_SubType,
sum(dbo.WarehouseProductQuantity.actualQuantity - dbo.WarehouseProductQuantity.reservedQuantity) AS AvailQty
FROM
table
GROUP BY
dbo.WarehouseSubType1.name) s
left join table t on t.dbo.WarehouseSubType1.name = s.WH_SubType;
For reference see this question: How do I use "group by" with three columns of data?
UPDATE 2:
SELECT
dbo.WarehouseType.name AS Section,
dbo.WarehouseSubType.name AS WH_Type,
dbo.WarehouseSubType1.name AS WH_SubType,
dbo.Branch.name AS Branch,
SumTable.AvailQty,
SumTable.Tafsil,
dbo.Tafsil.description AS Product_Name
FROM
dbo.WarehouseSubType
INNER JOIN
dbo.WarehouseType
ON
(
dbo.WarehouseSubType.warehouseTypeId = dbo.WarehouseType.id)
INNER JOIN
dbo.WarehouseSubType1
ON
(
dbo.WarehouseSubType.id = dbo.WarehouseSubType1.warehouseSubTypeId)
INNER JOIN
dbo.Warehouse
ON
(
dbo.WarehouseSubType1.id = dbo.Warehouse.warehouseSubType1Id)
INNER JOIN
dbo.Branch
ON
(
dbo.Warehouse.branchId = dbo.Branch.id)
INNER JOIN
dbo.WarehouseProductQuantity
ON
(
dbo.Warehouse.id = dbo.WarehouseProductQuantity.warehouseId)
INNER JOIN
dbo.TafsilLink
ON
(
dbo.WarehouseProductQuantity.tafsilId = dbo.TafsilLink.sourceId)
INNER JOIN
dbo.Tafsil
ON
(
dbo.TafsilLink.targetId = dbo.Tafsil.id)
INNER JOIN
dbo.FinishProduct
ON
(
dbo.Tafsil.id = dbo.FinishProduct.tafsilId)
LEFT JOIN (SELECT
sum(dbo.WarehouseProductQuantity.actualQuantity - dbo.WarehouseProductQuantity.reservedQuantity) AS AvailQty,
dbo.WarehouseProductQuantity.tafsilId AS Tafsil
FROM
dbo.WarehouseProductQuantity
group by dbo.WarehouseProductQuantity.tafsilId) SumTable on dbo.Tafsil.id = SumTable.Tafsil
WHERE
WarehouseSubType1.warehouseSubTypeId IN (1,4)
You need to do something like
SELECT SUM(AvailQty), ... FROM ... WHERE ... GROUP BY WH_SubType
http://www.w3schools.com/sql/sql_func_sum.asp
http://www.w3schools.com/sql/sql_groupby.asp