Row and column total in dynamic pivot - sql-server-2008

In SQL Server 2008, I have a table (tblStock) with 3 columns:
PartCode (NVARCHAR (50))
StockQty (INT)
Location (NVARCHAR(50))
some example data below:
PartCode StockQty Location
......... ......... .........
A 10 WHs-A
B 22 WHs-A
A 1 WHs-B
C 20 WHs-A
D 39 WHs-F
E 3 WHs-D
F 7 WHs-A
A 9 WHs-C
D 2 WHs-A
F 54 WHs-E
How to create procedure to get the result as below?
PartCode WHs-A WHs-B WHs-C WHs-D WHs-E WHs-F Total
........ ..... ..... ..... ...... ..... ..... .....
A 10 1 9 0 0 0 20
B 22 0 0 0 0 0 22
C 20 0 0 0 0 0 20
D 2 0 0 0 0 39 41
E 0 0 0 3 0 0 3
F 7 0 0 0 54 0 61
Total 61 1 9 3 54 39 167
Your help is much appreciated, thanks.

SAMPLE TABLE
SELECT * INTO #tblStock
FROM
(
SELECT 'A' PartCode, 10 StockQty, 'WHs-A' Location
UNION ALL
SELECT 'B', 22, 'WHs-A'
UNION ALL
SELECT 'A', 1, 'WHs-B'
UNION ALL
SELECT 'C', 20, 'WHs-A'
UNION ALL
SELECT 'D', 39, 'WHs-F'
UNION ALL
SELECT 'E', 3, 'WHs-D'
UNION ALL
SELECT 'F', 7, 'WHs-A'
UNION ALL
SELECT 'A', 9, 'WHs-C'
UNION ALL
SELECT 'D', 2, 'WHs-A'
UNION ALL
SELECT 'F', 54, 'WHs-E'
)TAB
Get the columns for dynamic pivoting and replace NULL with zero
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + Location + ']', '[' + Location + ']')
FROM (SELECT DISTINCT Location FROM #tblStock) PV
ORDER BY Location
-- Since we need Total in last column, we append it at last
SELECT #cols += ',[Total]'
--Varible to replace NULL with zero
DECLARE #NulltoZeroCols NVARCHAR (MAX)
SELECT #NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+Location+'],0) AS ['+Location+']'
FROM (SELECT DISTINCT Location FROM #tblStock)TAB
ORDER BY Location FOR XML PATH('')),2,8000)
SELECT #NullToZeroCols += ',ISNULL([Total],0) AS [Total]'
You can use CUBE to find row and column total and replace NULL with Total for the rows generated from CUBE.
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT PartCode,' + #NulltoZeroCols + ' FROM
(
SELECT
ISNULL(CAST(PartCode AS VARCHAR(30)),''Total'')PartCode,
SUM(StockQty)StockQty ,
ISNULL(Location,''Total'')Location
FROM #tblStock
GROUP BY Location,PartCode
WITH CUBE
) x
PIVOT
(
MIN(StockQty)
FOR Location IN (' + #cols + ')
) p
ORDER BY CASE WHEN (PartCode=''Total'') THEN 1 ELSE 0 END,PartCode'
EXEC SP_EXECUTESQL #query
Click here to view result
RESULT
NOTE : If you want NULL instead of zero as values, use #cols instead of #NulltoZeroCols in dynamic pivot code
EDIT :
1. Show only Row Total
Do not use the code SELECT #cols += ',[Total]' and SELECT #NullToZeroCols += ',ISNULL([Total],0) AS [Total]'.
Use ROLLUP instead of CUBE.
2. Show only Column Total
Use the code SELECT #cols += ',[Total]' and SELECT #NullToZeroCols += ',ISNULL([Total],0) AS [Total]'.
Use ROLLUP instead of CUBE.
Change GROUP BY Location,PartCode to GROUP BY PartCode,Location.
Instead of ORDER BY CASE WHEN (PartCode=''Total'') THEN 1 ELSE 0 END,PartCode, use WHERE PartCode<>''TOTAL'' ORDER BY PartCode.
UPDATE : To bring PartName for OP
I am updating the below query to add PartName with result. Since PartName will add extra results with CUBE and to avoid confusion in AND or OR conditions, its better to join the pivoted result with the DISTINCT values in your source table.
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT P.PartCode,T.PartName,' + #NulltoZeroCols + ' FROM
(
SELECT
ISNULL(CAST(PartCode AS VARCHAR(30)),''Total'')PartCode,
SUM(StockQty)StockQty ,
ISNULL(Location,''Total'')Location
FROM #tblStock
GROUP BY Location,PartCode
WITH CUBE
) x
PIVOT
(
MIN(StockQty)
FOR Location IN (' + #cols + ')
) p
LEFT JOIN
(
SELECT DISTINCT PartCode,PartName
FROM #tblStock
)T
ON P.PartCode=T.PartCode
ORDER BY CASE WHEN (P.PartCode=''Total'') THEN 1 ELSE 0 END,P.PartCode'
EXEC SP_EXECUTESQL #query
Click here to view result

you need to use case based aggregation to pivot the data
To get the total row use union
In case the Location values are not known in advance, you need to construct a dynamic query
you can also use pivot keyword to do the same.
select partCode,
sum( case when Location='WHs-A' then StockQty
else 0 end
) as 'Whs-A',
sum( case when Location='WHs-B' then StockQty
else 0 end
) as 'Whs-B',
sum(StockQty) as 'Total'
from tblStock
group by partCode
union all
select 'Total' as 'partCode',
sum( case when Location='WHs-A' then StockQty
else 0 end ) as 'Whs-A',
sum( case when Location='WHs-B' then StockQty
else 0 end) as 'Whs-B',
sum(StockQty) as 'Total'
from tblStock

Related

Split comma separated values in a particular comma postion using SQL or SSRS report

I have a field in SSRS that is concatenated values like
1234,1456,3456,7890,3457,3245,4345
I need to break/split after 8th comma or in a particular position in next row like:
1234,1456,3456,
7890,3457,3245,
4345
Here values are dynamic but, we have to split/break at every 8th or particular comma
In your example text, all the values have four characters. If that is the case, a simple recursive CTE does what you want:
with cte as (
select convert(varchar(max), NULL) as val, convert(varchar(max), field) as rest, 0 as lev
from t
union all
select left(rest, 15) as val, stuff(rest, 1, 15, '') as rest, lev+1
from cte
where rest <> ''
)
select val
from cte
where lev > 0;
Here is a db<>fiddle.
Once you've grabbed a copy of DelimitedSplit8K_LEAD (as STRING_SPLIT has no concept of ordinal positions) you can split the string and then "re-aggregate" it.
Using SQL Server 2017+:
DECLARE #YourString varchar(8000) = '1234,1456,3456,7890,3457,3245,4345';
WITH Split AS(
SELECT DS.Item,
DS.ItemNumber,
(DS.ItemNumber - 1) / 3 AS Grp
FROM dbo.DelimitedSplit8K_LEAD(#YourString,',') DS)
SELECT STRING_AGG(S.Item,',') WITHIN GROUP (ORDER BY S.ItemNumber ASC) AS NewString
FROM Split S
GROUP BY S.Grp;
SQL Server 2016-:
DECLARE #YourString varchar(8000) = '1234,1456,3456,7890,3457,3245,4345';
WITH Split AS(
SELECT DS.Item,
DS.ItemNumber,
(DS.ItemNumber - 1) / 3 AS Grp
FROM dbo.DelimitedSplit8K_LEAD(#YourString,',') DS)
SELECT STUFF((SELECT ',' + sq.Item
FROM Split sq
WHERE sq.Grp = S.Grp
ORDER BY sq.ItemNumber
FOR XML PATH(''),TYPE).value('.','varchar(8000)'),1,1,'') AS MewString
FROM Split S
GROUP BY S.Grp;
If you use SQL Server 2016+, you may use an approach, based on JSON. Just transform the input text into a valid JSON array and parse this array with OPENJSON():
Example with text:
Statement:
DECLARE #json nvarchar(max) = N'1234,1456,3456,7890,3457,3245,4345'
SELECT CONCAT(
MAX(CASE WHEN CONVERT(int, [key]) % 3 = 0 THEN [value] END),
MAX(CASE WHEN CONVERT(int, [key]) % 3 = 1 THEN [value] END),
MAX(CASE WHEN CONVERT(int, [key]) % 3 = 2 THEN [value] END)
) AS OutputText
FROM OPENJSON(CONCAT(N'["', REPLACE(#json, N',', N',","'), N'"]'))
GROUP BY (CONVERT(int, [key]) / 3)
Result:
---------------
OutputText
---------------
1234,1456,3456,
7890,3457,3245,
4345
Example with table:
Table:
CREATE TABLE Data (TextData nvarchar(max))
INSERT INTO Data (TextData)
VALUES (N'1234,1456,3456,7890,3457,3245,4345')
Statement:
SELECT d.TextData, c.OutputData
FROM Data d
CROSS APPLY (
SELECT CONCAT(
MAX(CASE WHEN CONVERT(int, [key]) % 3 = 0 THEN [value] END),
MAX(CASE WHEN CONVERT(int, [key]) % 3 = 1 THEN [value] END),
MAX(CASE WHEN CONVERT(int, [key]) % 3 = 2 THEN [value] END)
) AS OutputData
FROM OPENJSON(CONCAT(N'["', REPLACE(d.TextData, N',', N',","'), N'"]'))
GROUP BY (CONVERT(int, [key]) / 3)
) c
Result:
---------------------------------------------------
TextData OutputData
---------------------------------------------------
1234,1456,3456,7890,3457,3245,4345 1234,1456,3456,
1234,1456,3456,7890,3457,3245,4345 7890,3457,3245,
1234,1456,3456,7890,3457,3245,4345 4345

SQL Server Row totals in pivot query

I am trying to make a row in the end of the result set that shows the totals.
My query is this:
SELECT
[ ] = ISNULL(CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente, 'TOTAL'),
[2016-11-01] = MAX([2016-11-01]),
[2016-11-02] = MAX([2016-11-02]),
[2016-11-03] = MAX([2016-11-03]),
[2016-11-04] = MAX([2016-11-04]),
TOTAL = COUNT([2016-11-01]) + COUNT([2016-11-02]) + COUNT([2016-11-03]) + COUNT([2016-11-04])
FROM
(
SELECT GEN_Paciente.GEN_idPaciente,COALESCE(GEN_ape_paternoPaciente, '')+' '+COALESCE(GEN_ape_maternoPaciente, '')+' '+COALESCE(GEN_nombrePaciente, '') AS nombrePaciente,HOS_fechaCategorizacion,HOS_nivel_riesgoCategorizacion+CAST(HOS_nivel_dependenciaCategorizacion AS VARCHAR) as riesgoDependencia
FROM HOS_Categorizacion
INNER JOIN HOS_Hospitalizacion
ON HOS_Hospitalizacion.HOS_idHospitalizacion = HOS_Categorizacion.HOS_idHospitalizacion
INNER JOIN GEN_Paciente
ON GEN_Paciente.GEN_idPaciente = HOS_Hospitalizacion.GEN_idPaciente
WHERE HOS_nivel_riesgoCategorizacion IS NOT NULL
) src
PIVOT
(
MAX(riesgoDependencia)
for HOS_fechaCategorizacion in ([2016-11-01],[2016-11-02],[2016-11-03],[2016-11-04])
) p
GROUP BY
ROLLUP(CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente)
This gives me this result:
But as you can see the totals for the rows are right but the totals for the columns are wrong because I am using MAX instead of COUNT, but I only need COUNT in the TOTAL row, the others have to be MAX, so I wrote this query:
SELECT
[ ] = ISNULL(CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente, 'TOTAL'),
[2016-11-01] = CASE WHEN CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente IS NOT NULL THEN MAX([2016-11-01]) ELSE COUNT([2016-11-01]) END,
[2016-11-02] = CASE WHEN CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente IS NOT NULL THEN MAX([2016-11-02]) ELSE COUNT([2016-11-02]) END,
[2016-11-03] = CASE WHEN CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente IS NOT NULL THEN MAX([2016-11-03]) ELSE COUNT([2016-11-03]) END,
[2016-11-04] = CASE WHEN CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente IS NOT NULL THEN MAX([2016-11-04]) ELSE COUNT([2016-11-04]) END,
TOTAL = COUNT([2016-11-01]) + COUNT([2016-11-02]) + COUNT([2016-11-03]) + COUNT([2016-11-04])
FROM
(
SELECT GEN_Paciente.GEN_idPaciente,COALESCE(GEN_ape_paternoPaciente, '')+' '+COALESCE(GEN_ape_maternoPaciente, '')+' '+COALESCE(GEN_nombrePaciente, '') AS nombrePaciente,HOS_fechaCategorizacion,HOS_nivel_riesgoCategorizacion+CAST(HOS_nivel_dependenciaCategorizacion AS VARCHAR) as riesgoDependencia
FROM HOS_Categorizacion
INNER JOIN HOS_Hospitalizacion
ON HOS_Hospitalizacion.HOS_idHospitalizacion = HOS_Categorizacion.HOS_idHospitalizacion
INNER JOIN GEN_Paciente
ON GEN_Paciente.GEN_idPaciente = HOS_Hospitalizacion.GEN_idPaciente
WHERE HOS_nivel_riesgoCategorizacion IS NOT NULL
) src
PIVOT
(
MAX(riesgoDependencia)
for HOS_fechaCategorizacion in ([2016-11-01],[2016-11-02],[2016-11-03],[2016-11-04])
) p
GROUP BY
ROLLUP(CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente)
But that is not working
Thanks for your help!!
If I understand this correctly you want to count all columns which are not null. In this case you should just look at the condition IS NULL and not at the actual value at all. Try this:
DECLARE #tbl TABLE(ID INT IDENTITY, val1 VARCHAR(100),val2 VARCHAR(100),val3 VARCHAR(100));
INSERT INTO #tbl VALUES
('row1_val1','row1_val2',NULL)
,('row2_val1','row2_val2','row2_val3')
,(NULL,'row2_val2',NULL)
,(NULL,NULL,'row2_val3')
,(NULL,NULL,NULL);
SELECT *
,CASE WHEN val1 IS NULL THEN 0 ELSE 1 END
+CASE WHEN val2 IS NULL THEN 0 ELSE 1 END
+CASE WHEN val3 IS NULL THEN 0 ELSE 1 END AS CountOfValNotNull
FROM #tbl
UPDATE: Add a final Totals Row
You'd need ugly fiddling with a CTE, an additional sort column, UNION ALL to add another row and a sub_select.
Use the outer-most ORDER BY to get the artificial Totals-Row to the end
hint: Use the #tbl variable from above!
WITH SortedRows AS
(
SELECT ROW_NUMBER() OVER(ORDER BY ID) AS SortColumn
,*
,CASE WHEN val1 IS NULL THEN 0 ELSE 1 END
+CASE WHEN val2 IS NULL THEN 0 ELSE 1 END
+CASE WHEN val3 IS NULL THEN 0 ELSE 1 END AS CountOfValNotNull
FROM #tbl
)
SELECT tbl1.*
FROM
(
SELECT * FROM SortedRows
UNION ALL
SELECT 999999,0,'','','',(SELECT SUM(CountOfValNotNull) FROM SortedRows)
) AS tbl1
ORDER BY tbl1.SortColumn

Have Query Results Display In Different Columns

I am trying to avoid the creation of a table to have these results display (if possible). What I want to do is to essentially have the look of a table with my query results and have a column for fullitemlist, a column for 'has been ordered' and a column for 'has not been ordered'. Essentially I am trying to have a result set like such returned from my query:
> Zip = 55555
> fullitemlist ----- Has Been Ordered ---- Has Not Been Ordered
> Knife Set 1 0
> Butcher Block 0 1
> Dishwasher 0 1
> Hair Dryer 1 0
so on and so forth for all items in my tbl_itemlist. This is the 3 CTE queries I was trying to work with, but it returns everything in one giant list, not what I was after :)
Declare #zip varchar(5)
Set #zip = '55555'
;With CTE As
(
Select fullitemlist from tbl_ItemList
Where zip = #zip
)
,CTE2 As
(
Select case when hasbeenordered = 1 then 1 else 0 end as 'Has Been Ordered' from tbl_purchasehistory
WHERE itemid IN (Select itemid from tbl_ItemList where hasbeenordered = 1 and zip = #zip)
)
,CTE3 As
(
Select case when hasbeenordered = 0 then 1 else 0 end as as 'Has NEVER Been Ordered' from tbl_purchasehistory
WHERE itemid IN (Select itemid from tbl_ItemList where hasbeenordered = 0 and zip = #zip)
)
SELECT * from CTE
UNION ALL
SELECT * FROM CTE2
UNION ALL
SELECT * FROM CTE3
-- you may write your query like this according to your question instead of CTE ,union all,SubQuery this is the simplest way .
SELECT fullitemlist
,CASE
WHEN tp.hasbeenordered = 1
AND tI.hasbeenordered = 1
THEN 1
ELSE 0
END AS 'Has Been Ordered'
,CASE
WHEN tp.hasbeenordered = 0
AND ti.tp.hasbeenordered = 0
THEN 1
ELSE 0
END AS 'Has NEVER Been Ordered'
FROM tbl_ItemList ti
INNER JOIN tbl_purchasehistory tp ON ti.itemid = tp.ItemId
WHERE zip = #zip

Extract numeric part of string and get max value in column

I have a table foo that stores codes in format lnnnnn where l is at least one letter and n is numeric value. Both letters or numbers can be of various length, so trying to solve this like mentioned here won't work.
Example:
group | code
=============
1 | a0010
1 | a0012
1 | a0013
2 | bn0014
2 | bn0015
2 | bn0016
3 | u0017
3 | u0018
My task is to get current highest numeric value of this column in desired group, to generate new number (like sequence).
Note that I cannot redesign table and explode string and text parts.
So far I tried:
select
max(code rlike '[0-9]$')
from
foo
where
group = 2
but, sadly, regexp or rlike (synonyms) returns only 0 or 1 (matched or not matched).
One method is a brute force method:
select grp,
max(case when substr(code, 1, 1) between '0' and '9' then code + 0
when substr(code, 2, 1) between '0' and '9' then substr(code, 2) + 0
when substr(code, 3, 1) between '0' and '9' then substr(code, 3) + 0
when substr(code, 4, 1) between '0' and '9' then substr(code, 4) + 0
when substr(code, 5, 1) between '0' and '9' then substr(code, 5) + 0
when substr(code, 6, 1) between '0' and '9' then substr(code, 6) + 0
when substr(code, 7, 1) between '0' and '9' then substr(code, 7) + 0
when substr(code, 8, 1) between '0' and '9' then substr(code, 8) + 0
end)
from foo
group by grp;
If your numeric codes is always four digits then you can do it like:
select groupid, max(right(code,4)) as maxcode
from foo
group by groupid
See it here on fiddle: http://sqlfiddle.com/#!2/775b3/2
If all numeric parts start with a 0:
select gp, max(cast(substr(code, instr(code, '0')) as unsigned))
from t
group by gp
See sqlfiddle
If not, for arbitrary numeric parts (that start with any digit):
select gp, max(cast(substr(code, instr(code, n)) as unsigned))
from t
join (select 0 n union select 1 union select 2 union select 3 union select 4 union select 5
union select 6 union select 7 union select 8 union select 9) x
group by gp
See sqlfiddle

count not null columns out of specific list of columns and then compare in where clause for each row

Table structure:
Table Structure http://imagebin.org/index.php?mode=image&id=238883
I want to fetch data from both the tables which satisfy some of the conditions like
WHERE batch='2009', sex='male',course='B.Tech', branch='cs', xth_percent>60,
x2percent>60, gradpercent>60 and (if ranktype='other' ) then
no._of_not_null_semester>number elseifranktype='Leet') then
no._of_not_null_semester>number-2
sem 1-8 contains percentage for 8 semesters, and I want to filter results for each student if they have cleared 3 semesters or 4 semester i.e. not null values out of 8 values
no._of_not_null_semester
needs to be calculated, it is not a part of database, need help with that as well.
Required Query
SELECT * FROM student_test
INNER JOIN master_test ON student_test.id=master_test.id
WHERE sex='male' and batch='2009' and course='B.Tech'
and xthpercent>60 and x2percent>60 and
WHEN ranktype='Leet' THEN
SUM(CASE WHEN sem1 IS NOT NULL THEN 1 ELSE 0
WHEN sem2 IS NOT NULL THEN 1 ELSE 0
WHEN sem3 IS NOT NULL THEN 1 ELSE 0
WHEN sem4 IS NOT NULL THEN 1 ELSE 0
WHEN sem5 IS NOT NULL THEN 1 ELSE 0) >2
ELSE
SUM(CASE WHEN sem1 IS NOT NULL THEN 1 ELSE 0
WHEN sem2 S NOT NULL THEN 1 ELSE 0
WHEN sem3 IS NOT NULL THEN 1 ELSE 0
WHEN sem4 IS NOT NULL THEN 1 ELSE 0
WHEN sem5 IS NOT NULL THEN 1 ELSE 0) >4
Without changing the structure you can't use COUNT to achieve this.
One way to solve the problem would be to create a semester table which would contain a row for each finished semester for each student. This would have a foreign key pointing to test_student.id and you could use COUNT(semester.id)
If that is an option for you, it would be the best solution.
EDIT:
Check this out, didn't test the query but should work generally
I decided to do the math in the select itself to prevent calculating the same thing twice.
The HAVING conditions are applied after your result is ready to deliver, just before a LIMIT.
In terms of speed optimization you could try and move the sSum block into the WHERE condition just like you had it before. Probably it doesn't make much of a difference
SUM() does not work because it is an aggregate function which summarizes values in a column
I did some changes to your query in addition:
don't SELECT *, select specific fields and add a table identifier. ( in this case I used the aliases s for student_test AND m for master_test )
you put s.batch = '2009' into single quotes - if the field batch is an integer field, you should use s.batch = 2009, which would prevent MySQL from casting every single row to string to be able to compare it (int = int much faster than cast(int as varchar) = varchar) same about the other numeric values in your table
The Query:
SELECT
s.id,
s.sex,
s.course,
s.branch,
(
IF ( m.sem1 IS NOT NULL, 1, 0 ) +
IF ( m.sem2 IS NOT NULL, 1, 0 ) +
IF ( m.sem3 IS NOT NULL, 1, 0 ) +
IF ( m.sem4 IS NOT NULL, 1, 0 ) +
IF ( m.sem5 IS NOT NULL, 1, 0 ) +
IF ( m.sem6 IS NOT NULL, 1, 0 ) +
IF ( m.sem7 IS NOT NULL, 1, 0 ) +
IF ( m.sem8 IS NOT NULL, 1, 0 )
) AS sSum
FROM
student_test s
INNER JOIN master_test m ON m.id = s.id
WHERE
s.sex = 'male'
AND
s.batch = '2009' # I dont see this field in your database diagram!?
AND
s.course = 'B.Tech'
AND
m.xthpercent > 60
AND
m.x2percent > 60
HAVING
(
m.ranktype = 'OTHER'
AND
sSum > 4
)
OR
(
m.ranktype = 'LEET'
AND
sSum > 2
)
If you're generally interested in learning database design and usage I found an very interesting opportunity for you.
Stanford University offers a free database class "Introduction to databases". This is free and will cost you approx. 2 hours a week for 3 weeks, final exam included.
https://class2go.stanford.edu/db/Winter2013/preview/
SELECT
s.id,
s.sex,
s.course,
s.deptt,
m1.id,
m1.xthpercent,
m1.x2percent,
m1.sem1,
m1.sem2,
m1.sem3,
m1.ranktype,
m1.sem4,
m1.sem5,
m1.sem6,
m1.sem7,
m1.sem8,
m1.sSum
FROM
student_test s
INNER JOIN(SELECT m.id,
m.xthpercent,
m.x2percent,
m.sem1,
m.sem2,
m.sem3,
m.ranktype,
m.sem4,
m.sem5,
m.sem6,
m.sem7,
m.sem8,
( IF ( ceil(m.sem1)>0, 1, 0 ) +
IF ( ceil(m.sem2)>0, 1, 0 ) +
IF ( ceil(m.sem3)>0, 1, 0 ) +
IF ( ceil(m.sem4)>0, 1, 0 ) +
IF ( ceil(m.sem5)>0, 1, 0 ) +
IF ( ceil(m.sem6)>0, 1, 0 ) +
IF ( ceil(m.sem7)>0, 1, 0 ) +
IF ( ceil(m.sem8)>0, 1, 0 )
) AS sSum FROM master_test m
WHERE m.xthpercent>60 and
m.x2percent>60
HAVING (m.ranktype='Leet' AND sSum>2 )
OR
(m.ranktype != 'Leet') AND sSum>4 )
as m1 ON m1.id = s.id
WHERE
s.sex='Male'
and
s.course='B.Tech'
and
s.deptt='ELE'
This is the query finally I'm using, Love that query :)