T-SQL CASE (SQL Server 2000) - tsql

I have a T-SQL query that I need to total out the counts for the CASE statements.
I tried to add a UNION but I am getting an error:
All queries in an SQL statement containing a UNION operator must have
an equal number of expressions in their target lists.
Any ideas? Thanks.
Query:
SELECT
CustomerID, Name, DueDate,
CASE WHEN DATEDIFF(Month, PaymentDate, DueDate) >= 1
THEN PaymentAmount ELSE 0
END AS [Early],
CASE WHEN DATEDIFF(Month, PaymentDate, DueDate) >=0
THEN PaymentAmount ELSE 0
END AS [On Time],
CASE WHEN DATEDIFF(Month, PaymentDate, DueDate) = -1
THEN PaymentAmount ELSE 0
END AS [Late]
FROM
Customers
WHERE
DATEDIFF(MONTH, PaymentDate,DueDate), GetDate()) = 1
AND PaymentAmount= DuesAmount
UNION
SELECT
'-Total', '', CustomerID, Name, DueDate,
SUM(CASE WHEN DATEDIFF(Month, PaymentDate, DueDate) >= 1
THEN PaymentAmount ELSE 0 END) AS [Early],
SUM(CASE WHEN DATEDIFF(Month, PaymentDate, DueDate) >= 0
THEN PaymentAmount ELSE 0 END) AS [On Time],
SUM(CASE WHEN DATEDIFF(Month, PaymentDate, DueDate) = -1
THEN PaymentAmount ELSE 0 END) AS [Late]
FROM
Customers
WHERE
DATEDIFF(MONTH, PaymentDate,DueDate), GetDate()) = 1
AND PaymentAmount = DuesAmount

The error says, "All queries in a SQL statement containing a UNION operator must have an equal number of expressions in their target lists." What this means is that each SELECT must return the same number of expressions.
In the code sample you gave us, the first SELECT statement returns 6 expressions, while the second one returns 8:
SELECT CustomerID, -- 1
Name, -- 2
DueDate, -- 3
CASE ... END AS [Early], -- 4
CASE ... END AS [On Time], -- 5
CASE ... END AS [Late] -- 6
...
UNION
SELECT '-Total', -- 1
'', -- 2
CustomerID, -- 3
Name, -- 4
DueDate, -- 5
SUM(CASE ... END) AS [Early], -- 6
SUM(CASE ... END) AS [On Time], -- 7
SUM(CASE ... END) AS [Late] -- 8
...
See how the first SELECT returns 6 expressions, but the second returns 8? In a UNION, all the SELECT statements must return the same number of expressions.
You can return NULL in the first query for columns that don't have a match in the second, if necessary. For example:
SELECT NULL as [RowType], -- 1
NULL as [Padding], -- 2
CustomerID, -- 3
Name, -- 4
DueDate, -- 5
CASE ... END AS [Early], -- 6
CASE ... END AS [On Time], -- 7
CASE ... END AS [Late] -- 8
...
UNION
SELECT '-Total', -- 1
'', -- 2
CustomerID, -- 3
Name, -- 4
DueDate, -- 5
SUM(CASE ... END) AS [Early], -- 6
SUM(CASE ... END) AS [On Time], -- 7
SUM(CASE ... END) AS [Late] -- 8
...
Also, note that you don't have a comma after the DueDate column.

Related

postgres remove blank values from grouping

I have a rollup SQL statement that I'm trying to covert over from Oracle into PostGresSql. Overall the results look correct except I'm getting a blank value in the grouping column and I'm not sure how to get rid of it.
Right now I have:
SELECT
COALESCE(CASE WHEN GROUPING(COUNTY) = 1 THEN 'TOTAL' else county::text END) as COUNTY
,COUNT(CASE WHEN STV_TO_GAS THEN 1 END) as STOVE_TO_GAS_SUM
,COUNT(CASE WHEN FIRE_TO_GAS THEN 1 END) as FIRE_TO_GAS_SUM
,COUNT(CASE WHEN PELLET_TO_GAS THEN 1 END) as PELLET_TO_GAS_SUM
,COUNT(CASE WHEN STV_TO_ELECTRIC THEN 1 END) as STOVE_TO_ELECTRIC_SUM
,COUNT(CASE WHEN FIRE_TO_ELECTRIC THEN 1 END) as FIRE_TO_ELECTRIC_SUM
,COUNT(CASE WHEN PELLET_TO_ELECTRIC THEN 1 END) as PELLET_TO_ELECTRIC_SUM
,COUNT(CASE WHEN MERIDIAN THEN 1 END) as WITHIN_MERIDIAN_SUM
,count(CASE WHEN hb357.stv_to_gas then 1 END) +
count(CASE WHEN hb357.fire_to_gas then 1 END) +
count(CASE WHEN hb357.pellet_to_gas then 1 END) +
count(CASE WHEN hb357.stv_to_electric then 1 END) +
count(CASE WHEN hb357.fire_to_electric then 1 END) +
count(CASE WHEN hb357.pellet_to_electric then 1 END) +
count(CASE WHEN hb357.meridian then 1 END ) AS county_totals
FROM woodburn.HB357
WHERE app_status IN ('pending','approved')
AND (COUNTY IS NOT NULL OR trim(COUNTY) <> '')
GROUP BY rollup (county)
but its still returning a blank value in the county column
I've also trued changing the first case statement to
COALESCE(CASE
WHEN GROUPING(COUNTY) = 1 THEN 'TOTAL'
WHEN TRIM(COUNTY) != '' AND COUNTY IS NOT NULL then county
END) as COUNTY
but its returning a null row for county
FINAL SOLUTION
After trying all things suggested I essentially implemented what Jorge Campos recommended by doing the following:
SELECT
COALESCE(CASE
WHEN GROUPING(COUNTY) = 1 THEN 'TOTAL'
WHEN TRIM(COUNTY) != '' then county
END) as COUNTY
,COUNT(CASE WHEN STV_TO_GAS THEN 1 END) as STOVE_TO_GAS_SUM
,COUNT(CASE WHEN FIRE_TO_GAS THEN 1 END) as FIRE_TO_GAS_SUM
,COUNT(CASE WHEN PELLET_TO_GAS THEN 1 END) as PELLET_TO_GAS_SUM
,COUNT(CASE WHEN STV_TO_ELECTRIC THEN 1 END) as STOVE_TO_ELECTRIC_SUM
,COUNT(CASE WHEN FIRE_TO_ELECTRIC THEN 1 END) as FIRE_TO_ELECTRIC_SUM
,COUNT(CASE WHEN PELLET_TO_ELECTRIC THEN 1 END) as PELLET_TO_ELECTRIC_SUM
,COUNT(CASE WHEN MERIDIAN THEN 1 END) as WITHIN_MERIDIAN_SUM
,count(CASE WHEN hb357.stv_to_gas then 1 END) +
count(CASE WHEN hb357.fire_to_gas then 1 END) +
count(CASE WHEN hb357.pellet_to_gas then 1 END) +
count(CASE WHEN hb357.stv_to_electric then 1 END) +
count(CASE WHEN hb357.fire_to_electric then 1 END) +
count(CASE WHEN hb357.pellet_to_electric then 1 END) +
count(CASE WHEN hb357.meridian then 1 END ) AS county_totals
FROM woodburn.HB357
WHERE app_status IN ('pending','approved')
AND COUNTY IS NOT NULL
AND TRIM(COUNTY) != ''
GROUP BY rollup (county)

Why is there a difference in my SQL output

This is puzzling me no end, and I know it might be tough without the data but thought it might be a longshot to post here.
Here goes, the first code I received was this
USE [Radiotherapy]
GO
if exists (
select * from tempdb.dbo.sysobjects o
where o.xtype in ('U')
and o.id = object_id(N'tempdb..#MySampleTemp')
)
DROP TABLE #MySampleTemp;
if exists (
select * from tempdb.dbo.sysobjects o
where o.xtype in ('U')
and o.id = object_id(N'tempdb..#MyPivotTemp')
)
DROP TABLE #MyPivotTemp;
SELECT [AttendanceNumber]
,CASE WHEN AgeAtExamDate BETWEEN 0 AND 5 THEN '0-5'
WHEN AgeAtExamDate BETWEEN 6 AND 18 THEN '6-18'
WHEN AgeAtExamDate BETWEEN 19 AND 150 THEN '19+'
ELSE 'Error' END AS AgeRange
,[LocalPatientIdentifier]
,[ExaminationDate]
,[ExamExaminationCode] INTO #MySampleTemp
FROM [dbo].[tblRadiologyData]
WHERE AttendanceSiteCode IN('CNM','RNM')
--AND AttendanceStatus NOT IN ( 'Appt', 'Booked In', 'Cancelled', 'Pending' )
--AND AttendancePatientGroup = 'Out Patient'
--AND AttendancePatientCategory IN ( 'EU', 'Military', 'N.H.S.' )
--AND AttendanceSourceName <> 'PACs Support'
AND [ExaminationDate] >= '1 OCTOBER 2015' --
ORDER BY [AttendanceNumber], CASE WHEN AgeAtExamDate BETWEEN 0 AND 5 THEN '0-5'
WHEN AgeAtExamDate BETWEEN 6 AND 18 THEN '6-18'
WHEN AgeAtExamDate BETWEEN 19 AND 150 THEN '19+'
ELSE 'Error' END, [LocalPatientIdentifier], [ExaminationDate], ExamExaminationCode
SELECT [AttendanceNumber],AgeRange,[LocalPatientIdentifier],[ExaminationDate], 1 AS ExamCount,
[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14] INTO #MyPivotTemp
FROM
(
SELECT *,
row_number() OVER(PARTITION BY [AttendanceNumber]
ORDER BY [AttendanceNumber], [LocalPatientIdentifier]) rn
FROM #MySampleTemp
) AS st
pivot
(
MAX(ExamExaminationCode)
FOR rn in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14])
) AS pivottable
SELECT
[1] AS Exam01,
[2] AS Exam02,
[3] AS Exam03,
[4] AS Exam04,
[5] AS Exam05,
[6] AS Exam06,
[7] AS Exam07,
[8] AS Exam08,
[9] AS Exam09,
[10] AS Exam10,
[11] AS Exam11,
[12] AS Exam12,
[13] AS Exam13,
[14] AS Exam14,
COUNT(ExamCount) AS [No. Attendances]
FROM #MyPivotTemp
GROUP BY [1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14]
ORDER BY [1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14]
What I tried to do was replicate this in query as follows:
USE [Radiotherapy]
;With CTE AS (SELECT s.attendanceNumber,
MAX(CASE WHEN s.rnk = 1 THEN s.ExamExaminationCode END) as examCode1,
MAX(CASE WHEN s.rnk = 2 THEN s.ExamExaminationCode END) as examCode2,
MAX(CASE WHEN s.rnk = 3 THEN s.ExamExaminationCode END) as examCode3,
MAX(CASE WHEN s.rnk = 4 THEN s.ExamExaminationCode END) as examCode4,
MAX(CASE WHEN s.rnk = 5 THEN s.ExamExaminationCode END) as examCode5,
MAX(CASE WHEN s.rnk = 6 THEN s.ExamExaminationCode END) as examCode6,
MAX(CASE WHEN s.rnk = 7 THEN s.ExamExaminationCode END) as examCode7,
MAX(CASE WHEN s.rnk = 8 THEN s.ExamExaminationCode END) as examCode8,
MAX(CASE WHEN s.rnk = 9 THEN s.ExamExaminationCode END) as examCode9,
MAX(CASE WHEN s.rnk = 10 THEN s.ExamExaminationCode END) as examCode10,
MAX(CASE WHEN s.rnk = 11 THEN s.ExamExaminationCode END) as examCode11,
MAX(CASE WHEN s.rnk = 12 THEN s.ExamExaminationCode END) as examCode12,
MAX(CASE WHEN s.rnk = 13 THEN s.ExamExaminationCode END) as examCode13,
MAX(CASE WHEN s.rnk = 14 THEN s.ExamExaminationCode END) as examCode14
FROM (
SELECT [AttendanceNumber]
,[ExaminationDate]
,[ExamExaminationCode]
,ROW_NUMBER() OVER(PARTITION BY [AttendanceNumber]
ORDER BY [RadiologyID]) as rnk --Ordered by date ASC
FROM [Radiotherapy].[dbo].[tblRadiologyData] rd
where rd.ExaminationDate >= '01 october 2015'
and rd.AttendanceSiteCode IN('CNM','RNM') ) s
GROUP BY s.attendanceNumber)
Select CTE.examCode1,
CTE.examCode2,
CTE.examCode3,
CTE.examCode4,
CTE.examCode5,
CTE.examCode6,
CTE.examCode7,
CTE.examCode8,
CTE.examCode9,
CTE.examCode10,
CTE.examCode11,
CTE.examCode12,
CTE.examCode13,
CTE.examCode14,
COUNT(CTE.AttendanceNumber) as [No of occurances]
from CTE
GROUP by CTE.examCode1,
CTE.examCode2,
CTE.examCode3,
CTE.examCode4,
CTE.examCode5,
CTE.examCode6,
CTE.examCode7,
CTE.examCode8,
CTE.examCode9,
CTE.examCode10,
CTE.examCode11,
CTE.examCode12,
CTE.examCode13,
CTE.examCode14
ORDER BY CTE.examCode1
Great I thought until my code returned more results which puzzled me. Having broken it down I found the offending code from the original query:
ORDER BY [AttendanceNumber], CASE WHEN AgeAtExamDate BETWEEN 0 AND 5 THEN '0-5'
WHEN AgeAtExamDate BETWEEN 6 AND 18 THEN '6-18'
WHEN AgeAtExamDate BETWEEN 19 AND 150 THEN '19+'
ELSE 'Error' END, [LocalPatientIdentifier], [ExaminationDate], ExamExaminationCode
When I removed this from the first query the results matched, but my question is how and why is an ORDER BY affecting the output. I assumed this was just showing how the results are ordered? Understanding why code is doing what it's doing is something I really need to get my head around. Any advise more than welcome.
Probably it have something to do with this piece of code:
SELECT *,
row_number() OVER(PARTITION BY [AttendanceNumber]
ORDER BY [AttendanceNumber], [LocalPatientIdentifier]) rn
FROM #MySampleTemp
Obviously your ordering is not breaking a tie(it isn't deterministic) and it produces rank number differently when you have ordered data in temp table and when not ordered. Try to add some PK to your temp table so the above code will look like:
SELECT *,
row_number() OVER(PARTITION BY [AttendanceNumber]
ORDER BY [AttendanceNumber], [LocalPatientIdentifier], [SomePK]) rn
FROM #MySampleTemp
Then removing ordering from first select statement will not have an effect on the result set.

order by with operation on select case query

I want to rank a table by multi-columns and sum of each point that is decided by value.
For example, I can get some columns and each points by below query.
select
(case when seller=true then 50 else 0 end) as sel,
(case when buyer=true then 40 else 0 end) as buy
from company;
but I can't order by this values by like this query
select
(case when seller=true then 50 else 0 end) as sel,
(case when buyer=true then 40 else 0 end) as buy
from company
order by (sel + by);
or this
select
(case when seller=true then 50 else 0 end) as sel,
(case when buyer=true then 40 else 0 end) as buy,
(sell, buy) as sm
from company
order by sm;
How can I do that?
Oh, sorry, I found the answer.
select * from
(select
(case when seller=true then 50 else 0 end) as sel,
(case when buyer=true then 40 else 0 end) as buy
from company) as tmp
order by (tmp.sel + tmp.buy);

How to get data on a single row

I have table called RUGS with the data below. How do I write a TSQl query to get the data as shown in Output. I am not familiar with unPIVOT
`cono ARtype days Revenue PPD
140 MCD 5 1000 500
140 MRA 6 2000 600
140 MRA 7 3000 700
141 MCD 1 5000 100
141 MRA 2 6000 200
141 MRA 3 7000 300`
Result
140 MCD 5 1000 500 MRA 6 2000 600 MRA 7 3000 700
141 MCD 1 5000 100 MRA 2 6000 200 MRA 3 7000 300
Given that every cono will have exactly 3 records (as stated in the comments), a cte with row_number can be used with case statements.
If any have less than three records, you will see blanks and zeroes in the results. Any with more than three will not have all records represented.
Here is an example with #RUGS as a table variable:
declare #RUGS table (cono int, ARType char(3), [days] int, Revenue int, PPD int)
insert into #RUGS VALUES
(140,'MCD',5,1000,500)
,(140,'MRA',6,2000,600)
,(140,'MRA',7,3000,700)
,(141,'MCD',1,5000,100)
,(141,'MRA',2,6000,200)
,(141,'MRA',3,7000,300);
with cte as
(
select row_number() over(partition by cono order by (select 1)) as rn, * from #RUGS
)
select cono,
max(case when rn = 1 then ARType else '' end) as ARType1,
max(case when rn = 1 then days else '' end) as days1,
max(case when rn = 1 then Revenue else '' end) as Revenue1,
max(case when rn = 1 then PPD else '' end) as PPD1,
max(case when rn = 2 then ARType else '' end) as ARType2,
max(case when rn = 2 then days else '' end) as days2,
max(case when rn = 2 then Revenue else '' end) as Revenue2,
max(case when rn = 2 then PPD else '' end) as PPD2,
max(case when rn = 3 then ARType else '' end) as ARType3,
max(case when rn = 3 then days else '' end) as days3,
max(case when rn = 3 then Revenue else '' end) as Revenue3,
max(case when rn = 3 then PPD else '' end) as PPD3
from cte group by cono

Union Statement that can be changed to Case statement

Good Day Everyone!
well i have this kind of code and it kinda ugly,
a friend of mine told me i can implement Case Statements in here, but i do not know how or how would i implement, the code is long so if you could just help me to optimize my code i would appreciate it greatly!
PS. please be gentle to me, im new in T-sql :)
Thank yoU!
SELECT
SUM(CYJEWELRY) 'CY_Jewelry'
,SUM(CYAPPLICANCE) 'CY_Appliance'
,SUM(CYCELLPHONE) 'CY_Cellphone'
,SUM(PYJEWELRY) 'PY_Jewelry'
,SUM(PYAPPLIANCE) 'PY_Appliance'
,SUM(PYCELLPHONE) 'PY_Cellphone'
FROM
(
---TOTAL NUNG A FORMAT 0,0,0,0,0,0
--------------CURRENT YEAR JEWELRY
SELECT COUNT (*) AS CYJEWELRY,0 AS CYAPPLICANCE,0 AS CYCELLPHONE,0 AS PYJEWELRY,0 AS PYAPPLIANCE,0 AS PYCELLPHONE
FROM #TEMPTABLE1
WHERE (fld_StorageGroupID >= 3 and fld_StorageGroupID <= 14)
UNION
-----------CURRENT YEAR APPLIANCE
SELECT 0,COUNT(*),0,0,0,0
FROM #TEMPTABLE1
WHERE fld_StorageGroupID = 1
UNION
------------CURRENT YEAR CELLPHONE
SELECT 0,0,COUNT(*),0,0,0
FROM #TEMPTABLE1
WHERE fld_StorageGroupID = 2
UNION
---------------LAST YEAR JEWELRY
SELECT 0,0,0,COUNT(*),0,0
FROM #TEMPTABLE2
WHERE (fld_StorageGroupID >= 3 and fld_StorageGroupID <= 14)
UNION
-----------------------LAST YEAR APPLIANCE
SELECT 0,0,0,0,COUNT (*),0
FROM #TEMPTABLE2
WHERE fld_StorageGroupID = 1
UNION
-------------------------LAST YEAR CELLPHONE
SELECT 0,0,0,0,0,COUNT(*)
FROM #TEMPTABLE2
WHERE fld_StorageGroupID = 2
)A
Assuming your data is bit like this Sql Fiddle Example, try this for the sub query using SUM() and CASE.
SELECT SUM(CASE WHEN fld_StorageGroupID >= 3 and fld_StorageGroupID <= 14 ELSE 0 END) Col1And4,
SUM(CASE WHEN fld_StorageGroupID = 1 THEN 1 ELSE 0 END) Col2And5,
SUM(CASE WHEN fld_StorageGroupID = 2 THEN 1 ELSE 0 END) Col3And6
FROM #TEMPTABLE1
GROUP BY fld_StorageGroupID
Since you are applying the same filter for last 3 columns in the subquery, I have done only first 3 columns here.
EDIT:
I think this is better than above (Note: no need to use SUM() in the main query).
Fiddle Example with data
select col1_4 CY_Jewelry,
col2_5 CY_Appliance,
col3_6 CY_Cellphone,
col1_4 PY_Jewelry,
col2_5 PY_Appliance,
col3_6 PY_Cellphone
from (
select sum(case when id>= 3 and id <= 14 then 1 else 0 end) col1_4,
sum(case when id = 2 then 1 else 0 end) col2_5,
sum(case when id = 3 then 1 else 0 end) col3_6
from t
--group by id
) X