Issue Related to Query in SQL Server - sql-server

I have three table in SQL Server 2008:
Students
StudentId Name
1 Ghanshyam
2 John
3 Pravin
Exams
ExamId ExamName
1 English
2 Math
3 SS
4 Mechanical
Marks
MarksId StudentId ExamId Marks
1 1 1 90
2 1 2 45
3 1 3 89
4 1 4 56
5 1 5 93
I want to get result display in following format:
Name English Math SS Mechnical
Ghanshyam 90 45 89 56
John 89 38 78 87
Pravin 98 40 48 38
How can I get the above result based on above three table

This is an example of Pivot tables. See
http://msdn.microsoft.com/en-us/library/ms177410.aspx
for the explanation of how to do it in MS SQL Server. Note that it is also possible to do this with standard SQL, though a bit more complicated.

Take a look at the pivot operator / Complex pivot example:
http://msdn.microsoft.com/en-us/library/ms177410.aspx
VendorID is your Name, EmpX your subjects.

Why don't you try something like this, if you do not want a pivot table?
SELECT s.Name,
SUM(CASE WHEN e.ExamName = 'English' THEN m.Marks ELSE 0 END)
/ NULLIF(COUNT(CASE WHEN e.ExamName = 'English' THEN 1 ELSE 0 END), 0) as English,
SUM(CASE WHEN e.ExamName = 'Math' THEN m.Marks ELSE 0 END)
/ NULLIF(COUNT(CASE WHEN e.ExamName = 'Math' THEN 1 ELSE 0 END), 0) as Math,
SUM(CASE WHEN e.ExamName = 'SS' THEN m.Marks ELSE 0 END)
/ NULLIF(COUNT(CASE WHEN e.ExamName = 'SS' THEN 1 ELSE 0 END), 0) as SS,
SUM(CASE WHEN e.ExamName = 'Mechanical' THEN m.Marks ELSE 0 END)
/ NULLIF(COUNT(CASE WHEN e.ExamName = 'Mechanical' THEN 1 ELSE 0 END), 0) as Mechanical
FROM students s, marks m, exams e
WHERE m.StudentID = s.StudentID
AND m.ExamID = e.ExamID

Related

select from same column but multiple values SQL

My Table is as below:
EmpId section attn_status
101 Admin P
102 Admin P
103 Admin L
104 Admin A
105 Store P
106 Store L
107 Store A
108 Security P
109 Security L
110 Security P
111 Security P
I want to get results like below:
section Present Absent Late
Admin 2 1 1
Store 1 1 1
Security 3 0 1
This can be done using a group by and sum the values with a condition, like this
select t.section,
sum(case when t.attn_Status = 'P' then 1 else 0 end) as Present,
sum(case when t.attn_Status = 'L' then 1 else 0 end) as Late,
sum(case when t.attn_Status = 'A' then 1 else 0 end) as Absent
from mytable t
group by t.section
See also this DBFiddle

SUM() with entries from 2 table

Select p.pnum,
SUM(CASE WHEN P.NegativeScreen = 'Type99' THEN 1 ELSE 0 END) TotalDetected,
SUM(IIF(P.IsPositive = 1, 1,0)) TotalP,
SUM(CASE WHEN (P.MethId NOT IN (4, 8, 10, 25) THEN 1 ELSE 0 END) Total,
SUM(CASE WHEN (P.MethID IN (34,64) ) THEN 1 ELSE 0 END) TotalVal1,
SUM(CASE WHEN (P.MethID IN (16,64) ) THEN 1 ELSE 0 END) TotalVal2,
SUM(CASE WHEN (P.MethID IN (2,4,6,11,13,14,15,18,21,22,24,28,30,31) OR (P.MethID
= 1 AND P.TotalCount IS NOT NULL)) THEN 1 ELSE 0 END) TotalMethOther,
FROM tbl_plt p
GROUP BY P.PNum
Notice that the above query has all the fields from the tbl_plt table and SUM() is done on the fields.
Notice where I have MethID mentioned above. I need to check if those MethID exist in the tbl_plt table and if they exist in another table called TblOther. If so, tally it up accordingly.
Here is the fields in TblOther Table. Note that in TblOther table, we can have multiple PNums but the MethID will be different. Also note that for not all pNums will have entries in the TblOther table.
ID PNum MethID
1 232 32
2 232 64
3 232 10
4 104 14
5 104 54
6 22 4
7 4 13
I tried with LEFT JOIN with TblOther table but things gets messy as with the left join, it also tallies up incorrectly for places like:
SUM(CASE WHEN P.NegativeScreen = 'Type99' THEN 1 ELSE 0 END) TotalDetected,
SUM(IIF(P.IsPositive = 1, 1,0)) TotalP,
As an example for where I have:
SUM(CASE WHEN (P.MethID IN (34,64) ) THEN 1 ELSE 0 END)
it needs get the count of how many MethID exist in both the tblOther and tbl_plt for where MethID is 34 or 64 for the associated PNum.
It needs to do similarly for other places where MethID is mentioned.
I don't know enough about TblOther or it's join, but I suspect you might need to do the same group by (i.e., PNum) on it before joining on PNum. Then the left join will match either 0 or 1 records. Be sure to account for the null if there is no match.
You could start by getting the list of distinct PNum and MethIDs to use and then do your summing based on that list:
;WITH entries as (
SELECT DISTINCT PNum, MethID
FROM tblOther)
SELECT *
FROM entries
INNER JOIN tbl_plt
ON entries.PNum = tbl_plt.PNum
AND entries.MethID = tbl_plt.MethID
GROUP BY entries.PNum

Pivot SQL server results

My result set looks like:
ICount Owners ProgramCount
1344 AA 1
408 AA 2
185 AA 3
87 AA 4
54 AA 5
644 EA 1
81 EA 2
18 EA 3
3 EA 4
2 EA 5
4419 JA 1
1461 JA 2
700 JA 3
375 JA 4
209 JA 5
and I'd like the results to be:
Owner Total ProgramCount 1 ProgramCount 2 ProgramCount 3 ProgramCount 4 ProgramCount 5
AA 2078 1344 408 185 87 54
EA 748 644 81 18 3 2
JA 7164 4419 1461 700 375 209
where the Total column is the sum of ProgramCount 1 through 5.
How would I build my SQL to accomplish this?
A simple pivot in concert with a sum() over()
Example
Select *
From (
Select [Owners]
,Item = concat('Program Count ',[ProgramCount])
,[ICount]
,[Total] = sum([ICount]) over(partition by [Owners])
from YourTable
) src
Pivot (sum([ICount]) for [Item] in ([Program Count 1],[Program Count 2],[Program Count 3],[Program Count 4],[Program Count 5]) ) pvt
Order By [Owners]
Returns
select v.Owners as Owners,
sum(v.ICount) as Total,
sum(case when v.ProgramCount = 1 then v.ICount else 0 end) as ProgramCount1,
sum(case when v.ProgramCount = 2 then v.ICount else 0 end) as ProgramCount2,
sum(case when v.ProgramCount = 3 then v.ICount else 0 end) as ProgramCount3,
sum(case when v.ProgramCount = 4 then v.ICount else 0 end) as ProgramCount4,
sum(case when v.ProgramCount = 5 then v.ICount else 0 end) as ProgramCount5
from (
QUERY_WITH_YOUR_RESULT_SET
) as v(ICount, Owners, ProgramCount)
group by v.Owners
According to #Максим Золотенко's answer, You can use Conditional aggregation query with a group by like below
SELECT Owners,
SUM(ICount) AS Total,
SUM(CASE WHEN ProgramCount = 1 THEN ICount ELSE 0 END) AS ProgramCount_1,
SUM(CASE WHEN ProgramCount = 2 THEN ICount ELSE 0 END) AS ProgramCount_2,
SUM(CASE WHEN ProgramCount = 3 THEN ICount ELSE 0 END) AS ProgramCount_3,
SUM(CASE WHEN ProgramCount = 4 THEN ICount ELSE 0 END) AS ProgramCount_4,
SUM(CASE WHEN ProgramCount = 5 THEN ICount ELSE 0 END) AS ProgramCount_5
FROM TempTable
GROUP BY Owners
Live demo on db<>fiddle
Output

SUM values when conditions met

I have the following SQL Server table with the following data:
PRICE(decimal 9,2) PRICETYPE(int) EVENTDETAILID (int)
PRICE PRICETYPE EVENTDETAILID
------------------------------------------------
99 1 1
99 1 1
99 1 1
15 0 1
15 0 1
50 1 2
50 1 2
I want to SUM the PRICE of the results with the following conditions:
for each EVENTDETAILID, SUM every line with a pricetype is 0 and for every line per EVENTDETAILID pricetype is 1, then add it only 1 time.
For the above example the required output would be:
99 + 15 + 15 for eventDetailId = 1
50 for eventDetailsId = 2
I've tried the following but doesn't work as expected as I'm not able to add PRICE only once if PRICETYPE is 1:
SELECT
SUM(PRICE)
FROM
ReservationDetails
GROUP BY
eventDetail_id
You may phrase this as an aggregation (GROUP BY) query over the event detail ID. The sum can be broken into a conditional sum when the detail ID is 0, combined with the maximum price when the detail ID is 1. Since you told us that the price is always the same when PRICETYPE=1, therefore we can choose any single value.
SELECT
EVENTDETAILID,
SUM(CASE WHEN PRICETYPE = 0 THEN PRICE ELSE 0 END) +
MAX(CASE WHEN PRICETYPE = 1 THEN PRICE ELSE 0 END) AS total
FROM yourTable
GROUP BY
EVENTDETAILID
ORDER BY
EVENTDETAILID;
Demo

Using SUM in SQL Query with Filters

I am using SQL Server 2014 and I'm having a hard time with this query. Currently my query stands as follows:
SELECT b.FOH_PMSCONFNUM,
a.FOC_ACCOUNT,
a.FOC_TCODE,
a.[Net Amount]
FROM P5FOLIOHEADER b
LEFT JOIN
(SELECT
FOC_ACCOUNT,
FOC_TCODE,
SUM (FOC_NETAMOUNT) AS 'NetAmount'
FROM P5FOLIOCHARGE
GROUP BY FOC_ACCOUNT,FOC_TCODE) a ON a.FOC_ACCOUNT = b.FOH_ACCOUNT
And the output is as follows:
FOH_PMSCONFNUM FOC_ACCOUNT FOC_TCODE NetAmount
1216 52 ROOM 2500
1216 52 ROOM 2500
1216 52 ROOM 2500
1216 52 DRINKS 900
1216 52 DRINKS 600
1301 75 ROOM 1800
1301 75 ROOM 1800
1653 90 ROOM 3000
1653 90 TELEX 150
I need my output to be like this:
FOH_PMSCONFNUM FOC_ACCOUNT NetAmount(Room) NetAmount(Drinks) NetAmount(Telex)
1216 52 7500 1500 0
1301 75 3600 0 0
1653 90 3000 0 150
Is there a way to write this query without using the PIVOT syntax? I will need to ultimately append this query to another query.
Ideally, I'm looking for a query where I can modify this part in my existing query: SUM (FOC_NETAMOUNT) AS 'NetAmount' and make it into something like this:
SUM (FOC_NETAMOUNT) AS 'NetAmount(Room)' WHERE FOC_tcode ='ROOM'
SUM (FOC_NETAMOUNT) AS 'NetAmount(Drinks)' WHERE FOC_tcode ='DRINKS'
SUM (FOC_NETAMOUNT) AS 'NetAmount(Telex)' WHERE FOC_tcode ='TELEX'
It is just that I'm stuck as how to write the logic in SQL.
You can use a case expression in the sum to filter out the values:
select
b.FOH_PMSCONFNUM,
a.FOC_ACCOUNT,
a.FOC_TCODE,
sum(case a.FOC_TCODE when 'ROOM' then a.[Net Amount] else 0 end) as 'NetAmount(Room)',
sum(case a.FOC_TCODE when 'DRINKS' then a.[Net Amount] else 0 end) as 'NetAmount(Drinks)',
sum(case a.FOC_TCODE when 'TELEX' then a.[Net Amount] else 0 end) as 'NetAmount(Telex)',
from
P5FOLIOHEADER b
left join P5FOLIOCHARGE a on a.FOC_ACCOUNT = b.FOH_ACCOUNT
group by
a.FOC_ACCOUNT

Resources