XML won't output Divide by zero encountered in SQL Query - sql-server

I have a Query that selects Election data. Of course, when you start an election, there are 0 votes input for all candidates. But gradually, votes get entered. In order to get the percentage to output from the results, I took, number of votes multiplied by 100 then divided by total votes and I got my percentage.
Problem- once my query runs for the xml path, there is an error written in the top line of the xml document, "Divide by Zero error encountered". In order to bypass this, I just commented out the divide lines, but I would not like to do that. I figured, if I waited until there was a race that had votes in each field, I would then un-comment that line of code and let it output the percentage of only that race....until ALL races had at least some votes within them.
Here is my sql code:
:XML ON
select
max(case when seqnum = 1 then title1 end) as title1,
max(case when seqnum = 1 then [precinct percent] end) as PrecinctPercent,
max(case when seqnum = 1 then [candidate num] end) as WinnerNum,
max(case when seqnum = 1 then Votes end) as WinningVotes,
max(case when seqnum = 1 then party end) as WinningParty,
max(case when seqnum = 1 then leader end) as Winner,
max(case when seqnum = 1 then CAST(winner AS tinyint) end) as WinnerSelected,
max(case when seqnum = 1 then ((Votes * 100) / ([total vote])) end) as WinnerPercent,
max(case when seqnum = 2 then [candidate num] end) as LoserNum,
max(case when seqnum = 2 then Votes end) as LosingVotes,
max(case when seqnum = 2 then party end) as LosingParty,
max(case when seqnum = 2 then leader2 end) as Loser,
max(case when seqnum = 2 then ((Votes * 100) / ([total vote])) end) as LoserPercent,
max(case when seqnum = 2 then CAST(winner AS tinyint) end) as LoserSelected,
max(case when seqnum = 3 then title1 end) as title1,
max(case when seqnum = 3 then [precinct percent] end) as PrecinctPercent,
max(case when seqnum = 3 then [candidate num] end) as WinnerNum,
max(case when seqnum = 3 then Votes end) as WinningVotes,
max(case when seqnum = 3 then ((Votes * 100) / ([total vote])) end) as WinnerPercent,
max(case when seqnum = 3 then party end) as WinningParty,
max(case when seqnum = 3 then [first name]+ ' ' + [last name] end) as Winner,
max(case when seqnum = 3 then CAST(winner AS tinyint) end) as WinnerSelected,
max(case when seqnum = 4 then [precinct percent] end) as PrecinctPercent,
max(case when seqnum = 4 then [candidate num] end) as LoserNum,
max(case when seqnum = 4 then Votes end) as LosingVotes,
max(case when seqnum = 4 then ((Votes * 100) / ([total vote])) end) as LoserPercent,
max(case when seqnum = 4 then party end) as LosingParty,
max(case when seqnum = 4 then [first name]+ ' ' + [last name] end) as Loser,
max(case when seqnum = 4 then CAST(winner AS tinyint) end) as LoserSelected
from
(
select
r.title1,
r.[precinct percent],
r.[total vote],
rc.[race number],
rc.[candidate num],
rc.[Votes],
rc.[winner],
c.[party],
r.[leader],
r.[leader percent],
r.[leader2],
r.[leader2 percent],
c.[first name],
c.[last name],
row_number() over (partition by rc.[race number] order by votes desc) as seqnum
from dbo.[RACE CANDIDATES] rc
inner join dbo.[CANDIDATE] c on rc.[candidate num] = c.[candidate number]
inner join dbo.[RACE] r
on rc.[race number] = r.[race number]
) rc
group by rc.[race number]
FOR XML PATH ('ELECTION'), ROOT('root')
Is there a way I can have the select statement just "IGNORE" any fields that contain 0. Or choose to omit those that do contain 0 votes.
The total number of votes are being selected from the table "[RACE CANDIDATES]" if that helps. Hope it all makes sense.
Any input would be greatly appreciated.
Thanks All!

You can either put in a where in the sub select
WHERE r.[total vote] != 0
or you could use a case statment
CASE WHEN r.[total vote] = 0 THEN 0 ELSE Votes / r.[total vote] END

Related

Repeat Case Functions Used to Transpose

With the help from another poster, I developed the following code:
Select a.[PT_FIN]
,[RESULT_DT_TM1] = max(case when RN=1 then [RESULT_DT_TM] end)
,[Weight1] = max(case when RN=1 then [WEIGHT_RESULT] end)
,[Sysbp1] = max(case when RN=1 then [SYSBP_RESULT] end)
,[DiaBP1] = max(case when RN=1 then [DIABP_RESULT] end)
,[Temp1] = max(case when RN=1 then [TEMPERATURE_RESULT] end)
,[Oxy1] = max(case when RN=1 then [OXYGEN_SAT_RESULT] end)
,[Fio1] = max(case when RN=1 then [FIO2_RESULT] end)
,[Flow1] = max(case when RN=1 then [Flow_Rate_Result] end)
,[RESULT_DT_TM2] = max(case when RN=1 then [RESULT_DT_TM] end)
,[Weight2] = max(case when RN=1 then [Weight] end)
,[Sysbp2] = max(case when RN=1 then [Sysbp] end)
,[DiaBP2] = max(case when RN=1 then [DiaBP] end)
,[Temp2] = max(case when RN=1 then [TEMPERATURE_RESULT] end)
,[Oxy2] = max(case when RN=1 then [OXYGEN_SAT_RESULT] end)
,[Fio2] = max(case when RN=1 then [FIO2_RESULT] end)
,[Flow2] = max(case when RN=1 then [Flow_Rate_Result] end)
ETC
Each number at the end of the variable corresponds to a row a subject may have data (some subjects have 1 row of data, some may have 10). Is there an efficient way to repeat this code to capture a max of 10 rows of data so I do not have to add for example:
[RESULT_DT_TM3]= max(case when RN=3 then [RESULT_DT_TM] end)
[Weight3]= max(case when RN=3 then [WEIGHT_RESULT] end)
[RESULT_DT_TM4] = max(case when RN=4 then [RESULT_DT_TM] end)
[Weight4]= max(case when RN=4 then [Weight_Result] end)
....

Subquery a Cast Function

I have the following code which I'm using to transpose some data (see below); however, when running the code I received a 'Operand data type datetime2 is invalid for sum operator' error, which I believe is due to the fact the [RESULT_DT_TM] column has both date and time values. With the help from the outstanding contributors, I made what turns out to be a very simple code that removes the date from the [RESULT_DT_TM]:
select cast([RESULT_DT_TM] as time (0)) as [result_dt]
from ED_Vitals_Import_Master
I would like to include this code within the main query so I have use the new [result_dt] variable but am having trouble embedding it. Is it possible to do what I am seeking?
Select *
From (
Select a.[PT_FIN]
,B.*
From (Select *,RN=Row_Number() over (Partition By PT_FIN Order by [RESULT_DT_TM]) From ED_Vitals_Import_Master ) A
Cross Apply (values (concat('Time' ,RN),[RESULT_DT_TM])
,(concat('Weight' ,RN),[WEIGHT_RESULT])
,(concat('SysBp' ,RN),[SYSBP_RESULT])
,(concat('DiaBP',RN),[DIABP_RESULT])
,(concat('Temp' ,RN),[TEMPERATURE_RESULT])
,(concat('Oxy' ,RN),[OXYGEN_SAT_RESULT])
,(concat('Fio' ,Rn),[FIO2_RESULT])
) B(Item,Value)
) src
Pivot (sum(Value) for Item in ([RESULT_DT_TM1],[Weight1],[Sysbp1],[DiaBP1], [Temp1], [Oxy1], [Fio1]
,[RESULT_DT_TM2],[Weight2],[Sysbp2],[DiaBP2], [Temp2], [Oxy2], [Fio2]
,[RESULT_DT_TM3],[Weight3],[Sysbp3],[DiaBP3], [Temp3], [Oxy3], [Fio3]
,[RESULT_DT_TM4],[Weight4],[Sysbp4],[DiaBP4], [Temp4], [Oxy4], [Fio4]
) ) pvt
Since you are mixing datatypes... perhaps a conditional aggregation would be more useful.
Example
Select a.[PT_FIN]
,[RESULT_DT_TM1] = max(case when RN=1 then [RESULT_DT_TM] end)
,[Weight1] = max(case when RN=1 then [Weight] end)
,[Sysbp1] = max(case when RN=1 then [Sysbp] end)
,[DiaBP1] = max(case when RN=1 then [DiaBP] end)
,[Temp1] = max(case when RN=1 then [Temp] end)
,[Oxy1] = max(case when RN=1 then [Oxy] end)
,[Fio1] = max(case when RN=1 then [Fio] end)
,[RESULT_DT_TM2] = max(case when RN=2 then [RESULT_DT_TM] end)
,[Weight2] = max(case when RN=2 then [Weight] end)
,[Sysbp2] = max(case when RN=2 then [Sysbp] end)
,[DiaBP2] = max(case when RN=2 then [DiaBP] end)
,[Temp2] = max(case when RN=2 then [Temp] end)
,[Oxy2] = max(case when RN=2 then [Oxy] end)
,[Fio2] = max(case when RN=2 then [Fio] end)
--- Extend the Groups Here ---
From (Select *,RN=Row_Number() over (Partition By PT_FIN Order by [RESULT_DT_TM]) From ED_Vitals_Import_Master ) A
Group By a.[PT_FIN]

Switching rows with columns to generate a summary report in SQL Server

I have this query that geneartes data in format also shown:
SELECT TOP (10)
{ FN CONCAT({ FN CONCAT(dbo.BILL_INFO.BILL_NUMBER, '-')}, REPLICATE('0', 2 - LEN(RTRIM(dbo.BILL_INFO.PAY_MODE_ID)))
+ RTRIM(dbo.BILL_INFO.PAY_MODE_ID))} AS Id,
dbo.BILL_INFO.PAY_MODE_ID,
dbo.MASTER_PAY_MODE.NAME AS PAY_MODE
FROM dbo.BILL_INFO
INNER JOIN dbo.MASTER_PAY_MODE
ON dbo.BILL_INFO.PAY_MODE_ID = dbo.MASTER_PAY_MODE.ID
ORDER BY dbo.BILL_INFO.BILL_DATE DESC;
I need to transpose the result to this format:
I can do this using excel and a pivot but is there a way using SQL query?
Sample Data
Id |BILL_DATE |PAY_MODE
0000056-1002-18-10|2018-11-26 14:03:03.553|Bank Transfer
0001199-1002-18-05|2018-11-26 13:58:25.763|Credit Card
0000162-1030-18-05|2018-11-26 13:55:40.590|Credit Card
0001198-1002-18-05|2018-11-26 13:49:39.013|Credit Card
0001859-1030-18-04|2018-11-26 13:44:23.333|Free
0004443-1002-18-03|2018-11-26 13:42:27.550|Debit
0001532-1031-18-03|2018-11-26 13:36:23.010|Debit
0001916-1002-18-04|2018-11-26 13:33:23.157|Free
0001915-1002-18-04|2018-11-26 13:32:45.653|Free
0001914-1002-18-04|2018-11-26 13:30:35.580|Free
0004442-1002-18-03|2018-11-26 13:24:11.730|Debit
0004441-1002-18-03|2018-11-26 13:22:35.020|Debit
0004440-1002-18-03|2018-11-26 13:12:01.920|Debit
0004439-1002-18-03|2018-11-26 13:10:06.483|Debit
0001197-1002-18-05|2018-11-26 13:07:19.673|Credit Card
0001196-1002-18-05|2018-11-26 13:02:31.527|Credit Card
0004438-1002-18-03|2018-11-26 13:00:01.000|Debit
0001003-1030-18-03|2018-11-26 12:57:42.630|Debit
0001531-1031-18-03|2018-11-26 12:56:33.210|Debit
0001913-1002-18-04|2018-11-26 12:54:41.077|Free
Update
I have taken the solution provided by #[Tim Biegeleisen] as follows:
SELECT
MONTH(bi.BILL_DATE) AS [Month],
MAX(CASE WHEN m.NAME = 'Cheque' THEN bi.PAY_MODE_ID END) AS Cheque,
MAX(CASE WHEN m.NAME = 'Cash' THEN bi.PAY_MODE_ID END) AS Cash,
MAX(CASE WHEN m.NAME = 'Bank Transfer' THEN bi.PAY_MODE_ID END) AS [Bank Transfer],
MAX(CASE WHEN m.NAME = 'Credit Card' THEN bi.PAY_MODE_ID END) AS [Credit Card],
MAX(CASE WHEN m.NAME = 'Debit' THEN bi.PAY_MODE_ID END) AS Debit,
MAX(CASE WHEN m.NAME = 'Free' THEN bi.PAY_MODE_ID END) AS Free
FROM dbo.BILL_INFO bi
INNER JOIN dbo.MASTER_PAY_MODE m
ON bi.PAY_MODE_ID = m.ID
WHERE YEAR(bi.BILL_DATE) = 2018
GROUP BY
MONTH(bi.BILL_DATE) ORDER BY MONTH(bi.BILL_DATE)
You may do so via a pivot query, perhaps something alone these lines:
SELECT
YEAR(bi.BILL_DATE) + '-' + MONTH(bi.BILL_DATE) AS Date,
COUNT(CASE WHEN m.NAME = 'Cheque' THEN 1 END) AS Cheque,
COUNT(CASE WHEN m.NAME = 'Cash' THEN 1 END) AS Cash,
COUNT(CASE WHEN m.NAME = 'Bank Transfer' THEN 1 END) AS [Bank Transfer],
COUNT(CASE WHEN m.NAME = 'Credit Card' THEN 1 END) AS [Credit Card],
COUNT(CASE WHEN m.NAME = 'Debit' THEN 1 END) AS Debit,
COUNT(CASE WHEN m.NAME = 'Free' THEN 1 END) AS Free
FROM dbo.BILL_INFO bi
INNER JOIN dbo.MASTER_PAY_MODE m
ON bi.PAY_MODE_ID = m.ID
GROUP BY
YEAR(bi.BILL_DATE) + '-' + MONTH(bi.BILL_DATE);
Note that I am grouping the date column by month and year, because a given month appearing in the BILL_INFO table could belong to more than one year, in general.

SQL PIVOT on a variable amount of rows

I have the following data on a MSSQL Server:
Item No_ Unit Of Measure Qty Per Base UoM Rounding Precision
000001 PIECE 1 1.0
000001 PALLET 100 1.0
000001 BOX 12 1.0
000002 KG 1 1.0
000002 TON 1000 0.001
I am trying to get the following output:
Item No_ UoM1 Qty pb UoM1 RP1 UoM2 Qty pb UoM2 RP2 UoM3 Qty pb UoM3 RP3
000001 PIECE 1 1.0 PALLET 100 1.0 BOX 12 1.0
000002 KG 1 1.0 TON 1000 0.0001 NULL NULL NULL
I tried achieving this using the PIVOT operator but it does not seem te be correct.
What is the correct way to achieve my desired output?
For trully generic solution you need to use Dynamic-SQL.
But you say you want starting point, so I give you one. You can use:
LiveDemo
WITH cte AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY Item_No_ ORDER BY (SELECT 1)) AS rn
FROM #mytable
)
select Item_No_,
max(case when rn = 1 then Unit_Of_Measure end) UoM1,
max(case when rn = 1 then Qty_Per_Base_UoM end) [Qty pb UoM1],
max(case when rn = 1 then Rounding_Precision end) RP1,
max(case when rn = 2 then Unit_Of_Measure end) UoM2,
max(case when rn = 2 then Qty_Per_Base_UoM end) [Qty pb UoM2],
max(case when rn = 2 then Rounding_Precision end) RP2,
max(case when rn = 3 then Unit_Of_Measure end) UoM3,
max(case when rn = 3 then Qty_Per_Base_UoM end) [Qty pb UoM3],
max(case when rn = 3 then Rounding_Precision end) RP3,
max(case when rn = 4 then Unit_Of_Measure end) UoM4,
max(case when rn = 4 then Qty_Per_Base_UoM end) [Qty pb UoM4],
max(case when rn = 4 then Rounding_Precision end) RP4
from cte
group by Item_No_;
The point is that if your number of units is known in advance you can create hardcoded columns from 1 .. n.
For more info search Dynamic Pivot multiple columns. It is achievable, but first try to crack this solution.

SQL Server : convert rows to one row

I know SQL Server Pivot, but this time I think I will need something more complex then a simple pivoted value.
Here it is an SQL fiddle example.
So I have a table where I have maximum 3 rows for one startcity - endcity combination.
In a query I need to get these combinations in just one row, and I need just those combinations, where there are 3 rows.
Please advice,
You can do this as a crosstab like this.
with NumberedValues as
(
SELECT EndCity
, StartDate
, EndDate
, Price
, ROW_NUMBER() OVER(PARTITION BY StartCity, EndCIty ORDER BY StartDate) as RowNum
FROM [dbo].[BestPrice]
)
SELECT EndCity,
max(CASE WHEN RowNum = 1 THEN StartDate END) as StartDate1,
max(CASE WHEN RowNum = 1 THEN Enddate END) as EndDate1,
max(CASE WHEN RowNum = 1 THEN Price END) as Price1,
max(CASE WHEN RowNum = 2 THEN StartDate END) as StartDate2,
max(CASE WHEN RowNum = 2 THEN Enddate END) as EndDate2,
max(CASE WHEN RowNum = 2 THEN Price END) as Price2,
max(CASE WHEN RowNum = 3 THEN StartDate END) as StartDate3,
max(CASE WHEN RowNum = 3 THEN Enddate END) as EndDate3,
max(CASE WHEN RowNum = 3 THEN Price END) as Price3
FROM NumberedValues
group by EndCity

Resources