Combine like rows in table that used count function in the select - sql-server

I am writing a query to access health information from my student information system for state and county record compliance. We are using SQL Server 2000 (legacy system) as the backend. The query is this:
select
i.Description Immunization,
Case
When si.Exempt = 'P' Then Count (LName)
Else 0
END AS 'Personal Exempt',
Case
When si.Exempt = 'M' Then Count (LName)
Else '0'
END AS 'Medical Exempt',
Case
When si.Exempt = 'R' Then Count (LName)
Else 0
END AS 'Religious Exempt',
Case
When si.Exempt = 'I' Then Count (LName)--AS 'Personal Exemption'
Else '0'
END AS 'Had Illness'
from student cross join immunization i left join StImmunization si on si.sno = Student.sno and si.immcode = i.code
where Student.Status = 'A' and i.TotalReq > 0
Group BY i.Description, si.exempt
The output is this:
Immunization PersonalExempt MedicalExempt RelgiousExempt HadIllness
Chicken pox (Varicella) 0 0 0 6
Chicken pox (Varicella) 1 0 0 0
Hepatitis B 1 0 0 0
T_DAP 0 0 0 0
Polio 0 0 0 0
Diptheria, Tetanus,
Pertussis 0 0 0 0
Hepatitis B 0 0 0 0
Diptheria, Tetanus,
Pertussis 0 0 0 0
MMR 0 0 0 0
T_DAP 1 0 0 0
MMR 1 0 0 0
Polio 1 0 0 0
Chicken pox (Varicella) 1 0 0 0
I would like the output to combine the like rows of the columns so it looks like this and if necessary add like row and columns:
Imunization PersonalExempt Medical Exempt Religious Exempt Had Illness
Chicken pox (Varicella) 2 0 0 6
Hepatitis B 1 0 0 0
T_DAP 1 0 0 0
Polio 1 0 0 0
Diptheria, Tetanus,
Pertussis 1 0 0 0
Notice row one (below) is the sum of rows 2 and 13 (above). Any ideas on how to accomplish this?

Better to use SUM here -- then you can select a 1 or 0 to make the sum give the count.
Old SQL GROUP BY trick.
select
i.Description AS Immunization,
SUM(Case When si.Exempt = 'P' Then 1 Else 0 END) AS 'Personal Exempt',
SUM(Case When si.Exempt = 'M' Then 1 Else 0 END) AS 'Medical Exempt',
SUM(Case When si.Exempt = 'R' Then 1 Else 0 END) AS 'Religious Exempt',
SUM(Case When si.Exempt = 'I' Then 1 Else 0 END) AS 'Had Illness'
from student cross join immunization i left join StImmunization si on si.sno = Student.sno and si.immcode = i.code
where Student.Status = 'A' and i.TotalReq > 0
Group BY i.Description

Related

Group rows when using case expresion

I have the folloring query, that give me the next result:
select OBJ_POSITION,
CASE
WHEN (EVT_JOBTYPE = 'PM' and EVT_DESC like '%TMPL%') THEN (SUM(CONVERT(float, ACT_EST)))
ELSE '0'
END as HORAS_TMPL,
CASE
WHEN (EVT_JOBTYPE = 'CMS') THEN (SUM(CONVERT(float, ACT_EST)))
ELSE '0'
END as HORAS_SUST,
CASE
WHEN ((EVT_JOBTYPE = 'PM' and EVT_DESC like '%TMPL%') or (EVT_JOBTYPE = 'CMS')) THEN (SUM(CONVERT(float, ACT_EST)))
ELSE '0'
END as TOTAL_HORAS
from R5ACTIVITIES inner join R5EVENTS on ACT_EVENT = EVT_CODE inner join R5OBJECTS on EVT_OBJECT = OBJ_CODE
where OBJ_ORG = '156' and OBJ_POSITION like '156-EBM%' and EVT_STATUS = 'R' and EVT_TYPE in ('JOB', 'PPM')
group by OBJ_POSITION, EVT_JOBTYPE, EVT_DESC
OBJ_POSITION / HORAS_TMPL / HORAS_SUST / TOTAL_HORAS
156-EBM01 0 0 0
156-EBM01 0 0 0
156-EBM01 0 0 0
156-EBM02 0 0 0
156-EBM02 0 0 0
156-EBM03 0 0 0
156-EBM04 0 0 0
156-EBM04 8 0 8
156-EBM04 0.5 0 0.5
156-EBM04 0.75 0 0.75
156-EBM04 0 1.5 1.5
156-EBM05 0 0 0
156-EBM05 0 0 0
156-EBM05 0 0 0
The information is correct, but I only want one row per OBJ_Position, doing the sum of it's numbers (ACT_EST), like this:
OBJ_POSITION / HORAS_TMPL / HORAS_SUST / TOTAL_HORAS
156-EBM01 0 0 0
156-EBM02 0 0 0
156-EBM03 0 0 0
156-EBM04 9.25 1.5 10.75
156-EBM05 0 0 0
I've tried a lots of group by but none seems to work.
I think removing EVT_JOBTYPE from group by may work, but then it throws an error because its not an aggregate funcion. Same with EVT_DESC...
is this helpful.?
;with cte
As
(
select OBJ_POSITION,
CASE
WHEN (EVT_JOBTYPE = 'PM' and EVT_DESC like '%TMPL%') THEN (SUM(CONVERT(float, ACT_EST)))
ELSE '0'
END as HORAS_TMPL,
CASE
WHEN (EVT_JOBTYPE = 'CMS') THEN (SUM(CONVERT(float, ACT_EST)))
ELSE '0'
END as HORAS_SUST,
CASE
WHEN ((EVT_JOBTYPE = 'PM' and EVT_DESC like '%TMPL%') or (EVT_JOBTYPE = 'CMS')) THEN (SUM(CONVERT(float, ACT_EST)))
ELSE '0'
END as TOTAL_HORAS
from R5ACTIVITIES inner join R5EVENTS on ACT_EVENT = EVT_CODE inner join R5OBJECTS on EVT_OBJECT = OBJ_CODE
where OBJ_ORG = '156' and OBJ_POSITION like '156-EBM%' and EVT_STATUS = 'R' and EVT_TYPE in ('JOB', 'PPM')
group by OBJ_POSITION, EVT_JOBTYPE, EVT_DESC
)
Select OBJ_POSITION, SUM(HORAS_TMPL) as HORAS_TMPL,SUM(HORAS_SUST) as HORAS_SUST,SUM(TOTAL_HORAS) as TOTAL_HORAS
Group by OBJ_POSITION

pivot day of the month from row to column with sum value

I have a data with sum value and mapping to the day that matched with this SQL
sample data and code
http://sqlfiddle.com/#!3/ca364/6
but my problem is I can't pivot a date row to column
i need to pivot (query from sqlfiddle above) to shown as this example
Date 1 2 3 4 5 6 7 8 9 to end of the month
TAS0B065B999P999 0 0 0 0 0 4900 9900 0 -96600
TAS1B065B999P999 0 0 0 0 0 0 0 0 0
TAS2B065B999P999 0 0 0 0 0 0 0 0 0
TAS3B065B999P999 0 0 0 0 0 0 0 0 0
TAS4B065B999P999 0 0 0 0 0 0 0 0 0
TAS5B065B999P999 0 0 0 0 0 0 0 0 0
TAS6B065B999P999 0 0 0 0 0 0 0 0 0
TAS7B065B999P999 0 0 0 0 0 0 0 0 0
TAS8B065B999P999 0 0 0 0 0 0 0 0 0
TAS9B065B999P999 0 0 0 0 0 0 0 0 0
TASAB065B999P999 0 0 0 0 0 0 0 0 0
TDS1B065B999P999 0 0 0 0 0 0 0 0 0
TDS2B065B999P999 0 0 0 0 0 0 0 0 0
TDS3B065B999P999 0 0 0 0 0 0 0 0 0
TRS1B065B999P999 0 0 0 0 0 0 0 0 0
TRS2B065B999P999 0 0 0 -72900 0 74900 -74900 90900 0
TRS3B065B999P999 0 0 0 21100 0 0 0 0 0
Sample code
WITH t1
AS (SELECT dt,TERM,
SumCashOUT,
DATEADD(MONTH, DATEDIFF(MONTH, '1900-01-01', dt), '1900-01-01') AS firstInMonth,
DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, '1900-01-01', dt)+1, '1900-01-01')) AS lastInMonth
FROM
(
SELECT CONVERT( DATE, TA_DATE) AS dt,TERM,
DATENAME(dw, CONVERT( DATE, TA_DATE)) AS dn,
DATEPART(DW, CONVERT( DATE, TA_DATE)) AS dtdw,
OUT1 + OUT2 + OUT3 + OUT4 AS SumCashOUT
FROM CASH1609
GROUP BY TA_DATE,
TERM,
OUT1,
OUT2,
OUT3,
OUT4
) AS st
GROUP BY dt,TERM,
dn,
dtdw,
SumCashOUT),
Calendar
AS (SELECT DISTINCT
DATEADD(Day, c.number, t1.firstInMonth) AS d
FROM t1
JOIN master..spt_values AS c ON type = 'P'
AND DATEADD(DAY, c.number, t1.firstInMonth) BETWEEN t1.firstInMonth AND t1.lastInMonth)
SELECT DATEPART(dd, d) AS Date,TERM,
CASE
WHEN CONVERT( NUMERIC(16, 0), SumCashOUT) IS NULL
THEN 0
ELSE CONVERT(NUMERIC(16, 0), SumCashOUT)
END AS SumCashOUT
FROM calendar AS c
LEFT JOIN t1 ON t1.dt = c.d
LEFT JOIN holiday ON c.d = holiday.HDATE
ORDER BY DAte ASC;
You will have to use PIVOT Command in SQL Server.
This will deliver the desired output:
;WITH tab (TERM, DOM, CASH) AS
(
SELECT TERM,
DAY(CAST(TA_DATE AS DATE)) AS DOM,
OUT1 + OUT2 + OUT3 + OUT4 AS CASH
FROM CASH1609
)
SELECT *
FROM tab
PIVOT
(
SUM (CASH)
FOR DOM IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],
[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],
[22],[23],[24],[25],[26],[27],[28],[29],[30],[31])
) AS pvt
The "tab" CTE prepares the Columns DOM(Day-Of-Month) and CASH.
PIVOT needs an aggregate function (SUM in your case) AND the possible values for the pivot-column.
Note: This will deliver NULL for each non-existing DOM, just replace
SELECT * FROM tab
with
SELECT TERM, COALESCE([1],0), COALESCE([2],0), etc... FROM tab...

In SQL Server, Split bit column to 2 columns using PIVOT

I have a table as below
Name Grade SubjectAorB
Pooja B 1
Preeti C 0
Preeti C 1
Chintu A 1
Deepika B 0
Deepika B 1
Peter A 0
John A 0
Last column SubjectAorB has values as 0 and 1. 0 means Subject A and 1 means Subject B. A student can have either of the subject or both. I want output as below:
Name Grade Subject A Subject B
Pooja B 0 1
Preeti C 1 1
Chintu A 0 1
Deepika B 1 1
Peter A 1 0
John A 1 0
You can do this using conditional aggregation:
SELECT
Name,
Grade,
SubjectA = MAX(CASE WHEN SubjectAorB = 0 THEN 1 ELSE 0 END),
SubjectB = MAX(CASE WHEN SubjectAorB = 1 THEN 1 ELSE 0 END)
FROM #tbl
GROUP BY Name, Grade

Count data using SQL Server 2008

I'm using SQL Server 2008 and I have a big database, I need to count the data for every manzana but every rows is 0 so I don't know how to do that
SELECT
Manzana,
SUM(CASE WHEN Manzana IN( 'CBrc','CBrc1', 'CBrc2') THEN 1 ELSE 0 END )AS CBrc,
SUM(CASE WHEN Manzana IN ('W1','W11','W12','W13','W14','W15','W16') THEN 1 ELSE 0 END) AS W1,
SUM(CASE WHEN Manzana IN('PC1','PC11') THEN 1 ELSE 0 END) AS PC1,
SUM(CASE WHEN Manzana IN ('CLu','CLU1') THEN 1 ELSE 0 END) AS CLu,
SUM(CASE WHEN Manzana IN('S3','S31') THEN 1 ELSE 0 END) AS S3,
SUM(CASE WHEN Manzana IN ('C2L') THEN 1 ELSE 0 END) AS C2L,
SUM(CASE WHEN Manzana IN ('PCA') THEN 1 ELSE 0 END) AS PCA,
SUM(CASE WHEN Manzana IN ('ADO') THEN 1 ELSE 0 END) AS AD,
SUM(CASE WHEN Manzana IN ('PRC') THEN 1 ELSE 0 END) AS CBu,
SUM(CASE WHEN Manzana IN('SIN') THEN 1 ELSE 0 END) AS SIN_ACCESO_A_INFORMACION
FROM
dbo.Hoja3$
GROUP BY
Manzana
I need to obtain something like this
Manzana CBrc W1 PC1 CLU S3 C2L
5445 8 11 0 0 0 0
4545 15 0 30 0 0 0
5455 21 0 5 3 2 0
7893 0 0 3 1 0 0
1566 100 4 1 0 0 80
You can't group by Manzana and not group by Manzana. Also, from the sample data, I can tell that you haven't provided enough information. Just from the first row:
Manzana CBrc W1 PC1 CLU S3 C2L
5445 8 11 0 0 0 0
If Manzana is 5445, then what column has the value CBrc? It can't be the Manzana column, but has to be some other column. In this vacuum of information, I'm going to call the mystery column Code.
Then try this (of course, you'll need to put all your code groups in):
WITH CodeGroupings AS (
SELECT * FROM (VALUES -- Do this in a permanent table instead!
('CBrc%', 'CBrc'), -- can use wildcards
('W1_', 'W1'), -- or single letter wildcards
('PC1', 'PC1'), -- or just put individual values
('PC11', 'PC1'), -- mapping to the same group as the previous line
('SIN', 'SIN_ACCESO_A_INFORMACION')
) M (CodePattern, CodeGroup)
), ManzanaCodeGroups AS (
SELECT
H.Manzana,
CG.CodeGroup
FROM
dbo.Hoja3$ H
CROSS APPLY (
SELECT TOP 1 *
FROM CodeGroupings CG
WHERE H.Code LIKE CG.CodePattern
) CG
)
SELECT
*
FROM
ManzanaCodeGroups
PIVOT (Count(*) FOR (CodeGroup IN CBrc, W1, PC1, SIN_ACCESO_A_INFORMACION)) P
;
After reading your comment "I try to count how many Cbrc,Pc1, Clu etc I have in every Manzana" I see the problem.
You're using the IN operator incorrectly.
To test fo the occurrence of a substring use the CHARINDEX function:
SELECT
Manzana,
SUM( CASE WHEN CHARINDEX( 'SIN', Manzana ) > 0 THEN 1 ELSE 0 END ) AS SIN,
SUM( CASE WHEN CHARINDEX( 'PCA', Manzana ) > 0 THEN 1 ELSE 0 END ) AS PCA,
...
FROM
Hoja3$
GROUP BY
Manzana

Combine multiple rows into one row with same number of columns

I have results that have multiple rows for priority counts for specific locations. I would like to simply turn those results into a single row to display the same information.
My current code is:
SELECT t.city_nm as CITY
,sum(case when h.priority = 1 then 1 else 0 end)as Priority1
,sum(case when h.priority = 2 then 1 else 0 end)as Priority2
,sum(case when h.priority = 3 then 1 else 0 end)as Priority3
from SHIPMENT h
INNER JOIN PET_EVT_LOG e
on h.svc_id = e.svc_id
INNER JOIN LOCATION t
ON t.city_id = e.term_id
INNER JOIN CUSTOMER u
ON h.ship_cust = u.cust_id
where u.cust_nm = 'CAL NATURAL'
and e.evt_cd = 'ARRIVAL'
and e.evt_dt_tm > date(current timestamp) - 7 day
GROUP BY t.city_nm, h.priority;
My results look like this:
CITY Priority1 Priority 2 Priority3
Atlanta 7 0 0
Atlanta 0 25 0
Atlanta 0 0 3
Baltimore 3 0 0
Baltimore 0 12 0
Baltimore 0 0 1
Detroit 9 0 0
Detroit 0 32 0
Detroit 0 0 5
Where there is a number count in one row, the other two fields are ALWAYS 0, so they should easily be combined to produce results that look like this:
CITY Priority1 Priority 2 Priority3
Atlanta 7 25 3
Baltimore 3 12 1
Detroit 9 32 5
try replacing
GROUP BY t.city_nm, h.priority;
by
GROUP BY t.city_nm;

Resources