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...
Related
I have a dataset where I need to find the diseased patients in consecutive rows.
I'll share my sample dataset with a clear explanation.
ID Normal Des1 Des2 Des3 Des4
12 0 1 0 0 0
12 1 0 1 0 0
12 1 0 1 0 0
12 1 0 1 0 0
14 0 1 0 1 0
18 1 0 0 0 0
18 1 0 0 0 0
18 1 0 0 0 0
11 0 1 0 0 0
11 0 1 0 0 0
11 0 1 0 0 0
22 1 0 0 0 0
Here I specified the Diseased list of the dataset. I required the IDs for those who are in the same Disease in all the period.
Assume that I need an output for Patients who never fall in any Diseased criteria(IDs 18, 22) I stored it as a new set(Undiseased), Later I need to get the same model for Des1 patients (IDs 11). I tried the below code to fetch the data. but It returns partial output.
select ID from tablename where
(normal = '1' and Des1 = '0' and Des2 = '0' and Des3 = '0' and Des4 = '0')
group by ID
You can try the below query using COUNT (Transact-SQL)
function.
Create table MySampleTable (Id int, Des1 int, Des2 int, Des3 int)
insert into MySampleTable Values
(12, 0, 1, 0),
(12, 1, 0, 1),
(12, 1, 0, 1),
(18, 1, 0, 0),
(18, 1, 0, 0),
(11, 0, 1, 0),
(11, 0, 1, 0)
; with cte as (Select Id
, Count(distinct Des1) as TotDes1
, Count(distinct Des2) as TotDes2
, Count(distinct Des3) as TotDes3
from MySampleTable
group by Id
)
Select Id from cte where TotDes1 = 1
and TotDes2 = 1 and TotDes3 = 1
It looks like as shown below with the output.
Here is the live db<>fiddle demo.
You can also use the having clause as shown in the query below.
Select Id
/*
, Count(distinct Des1) as TotDes1
, Count(distinct Des2) as TotDes2
, Count(distinct Des3) as TotDes3
*/
from MySampleTable
group by Id
having Count(distinct Des1) = 1 and Count(distinct Des2) = 1
and Count(distinct Des3) = 1
Demo on db<>fiddle
You can achieve it in this simple way
;WITH cte_TempTable AS(
Select DISTINCT Id, Des1, Des2, Des3
from MySampleTable
)
SELECT Id
FROM cte_TempTable
GROUP BY Id
HAVING COUNT(Id) = 1
Output
You can use use apply :
select t.id
from table t cross apply
( values (Des1, 'Des1'), (Des2, 'Des2'), (Des3, 'Des3'), (Des4, 'Des4')
) tt(DiseasFlag, DiseasName)
where DiseasFlag = 1
group by t.id
having count(distinct DiseasName) = 1;
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
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
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
I have the first 4 columns of data, and I wan't to use the Ranking functions in the SQL 2008 R2 to derive the fifth column. What's the best way to partition the data into subgroups based on the nextiteminsubgroup and previousiteminsubgroup fields?
Group OrderInGroup NextItemInSubGroup PreviousItemInSubGroup SubGroup
1 1 1 0 1
1 2 1 1 1
1 3 1 1 1
1 4 0 1 1
1 5 0 0 2
1 6 0 0 3
1 7 1 0 4
1 8 1 1 4
1 9 0 1 4
2 1 0 0 1
2 2 0 0 2
2 3 0 0 3
2 4 1 0 4
2 5 0 1 4
3 1 0 0 1
4 1 0 0 1
4 2 0 0 2
4 3 0 0 3
A recursive CTE solution:
DECLARE #t TABLE
([Group] INT
,OrderInGroup INT
,NextItemInSubGroup INT
,PreviousItemInSubGroup INT
,SubGroup INT
)
INSERT #t
VALUES
(1,1,1,0,1),(1,2,1,1,1),(1,3,1,1,1),(1,4,0,1,1),(1,5,0,0,2),(1,6,0,0,3),
(1,7,1,0,4),(1,8,1,1,4),(1,9,0,1,4),(2,1,0,0,1),(2,2,0,0,2),(2,3,0,0,3),
(2,4,1,0,4),(2,5,0,1,4),(3,1,0,0,1),(4,1,0,0,1),(4,2,0,0,2),(4,3,0,0,3)
;WITH recCTE
AS
(
SELECT [Group], OrderInGroup,NextItemInSubGroup , PreviousItemInSubGroup, 1 AS subgroup
FROM #t
WHERE OrderInGroup = 1
UNION ALL
SELECT r.[Group], t.OrderInGroup,t.NextItemInSubGroup , t.PreviousItemInSubGroup,
CASE WHEN r.NextItemInSubGroup = 1 THEN r.subgroup ELSE r.subgroup + 1 END
FROM recCTE AS r
JOIN #t AS t
ON t.[Group] = r.[Group]
AND t.OrderInGroup = r.OrderInGroup + 1
)
SELECT * FROM recCTE
ORDER BY [Group],OrderInGroup ;
P.S. it's best practice to avoid using SQL keywords (e.g. GROUP) as table/column names
Seems like 0 and 0 restart the ranking.
Select
Rank() Over (
Partition By
[Group]
, Case When [NextItemInSubGroup] + [PreviousItemInSubGroup] = 0
Then 0
Else 1
End
Order By [OrderInGroup]
) as [SubGroup]
From Your_Table;