SSRS 2008 - error message when dividing by zero - reporting-services

In my Texbox expression, giving divide by zero errors, I had:
=SUM ((Sum( IIF(Fields!Pay.Value = "G" , Fields!EndBal.Value * 1, Fields!EndBal.Value * 0 )) - Sum( IIF(Fields!Pay.Value = "N" , Fields!EndBal.Value * 1, Fields!EndBal.Value * 0 )) ) / (Sum( IIF(Fields! Pay.Value = "G" , Fields!EndBal.Value * 1, Fields!EndBal.Value * 0 ))) )
Solution:
In the Menu > Report > Report Properties > Code I pasted the below code:
Public Function Divider (ByVal Dividend As Double, ByVal Divisor As Double)
If IsNothing(Divisor) Or Divisor = 0
Return 0
Else
Return Dividend/Divisor
End If
End Function
In the Texbox expression now I have entered this, calling the function created:
=code.divider((Sum( IIF(Fields!Pay.Value = "G" , Fields!EndBal.Value * 1, Fields!EndBal.Value * 0 )) - Sum( IIF(Fields!Pay.Value = "N" , Fields!EndBal.Value * 1, Fields!EndBal.Value * 0 )) ) , (Sum( IIF(Fields!Pay.Value = "G" , Fields!EndBal.Value * 1, Fields!EndBal.Value * 0 ))) )
It still gives me the error when dividing by zero. What am I doing wrong here? Am I also missing the total sum, which I had in the first expression.
thank you!

This worked for me:
= Sum(
Code.Divider(
Sum(
IIF(
Fields!Pay.Value = "G" , Fields!EndBal.Value * 1, Fields!EndBal.Value * 0
)
) - Sum(
IIF(
Fields!Pay.Value = "N" , Fields!EndBal.Value * 1, Fields!EndBal.Value * 0
)
), Sum(
IIF(
Fields! Pay.Value = "G" , Fields!EndBal.Value * 1, Fields!EndBal.Value * 0
)
)
)
)
But your total Sum() before the divider doesn't do anything, cause you divided the aggregated values already.

I had a fix on my data and it actually works now , using the same I was trying before:
=code.divider((Sum( IIF(Fields!Pay.Value = "G" , Fields!EndBal.Value * 1, Fields!EndBal.Value * 0 )) - Sum( IIF(Fields!Pay.Value = "N" , Fields!EndBal.Value * 1, Fields!EndBal.Value * 0 )) ) , (Sum( IIF(Fields!Pay.Value = "G" , Fields!EndBal.Value * 1, Fields!EndBal.Value * 0 ))) )
==> it does not needs the SUM in the beggining.

Related

SQLSERVER Running Balance

Actually i have problem on my query to get the running balance , i have debit and credit transaction i need one column to showing the cumulative running balance this is the code i used :
Select * From (
Select D.AccNo, H.[Date], A.AccountName, H.TrxNo,
(Case When ((D.Remark = '') or (D.Remark is Null)) Then H.Trxnote Else D.Remark End) As TrxDetailDescA,
(D.Debit * 1) AS DebitValue, (D.Credit * 1) AS CreditValue,SUM(COALESCE(D.Debit, 0) - COALESCE(D.Credit, 0)) AS Balance
From TblHeadTrans H, TblTransDetails D, TblAccount A
Where H.Guid = D.[LineNo]
And D.AccNo = A.AccountNo
And H.[Date] >= '01-01-2022' And H.[Date] <= '10-07-2022' And D.AccNo >= '1003'
group by AccNo,H.[Date],A.AccountName,H.TrxNo,D.Remark,h.Trxnote,d.Debit,d.Credit
Union All
Select D.AccNo, Null As TrxDate, A.AccountName, Null As TrxNo,
'Opening Balance' As TrxDetailDesc,
Case When (Sum(D.Debit * 1) - Sum(D.Credit *1)) < 0 then 0
Else (Sum(D.Debit * 1) - Sum(D.Credit * 1)) End As DebitValue,
Case When (Sum(D.Credit * 1) - Sum(D.Debit * 1)) < 0 then 0
Else (Sum(D.Credit * 1) - Sum(D.Debit * 1)) End As CreditValue
, SUM(COALESCE(d.Debit, 0) - COALESCE(d.credit, 0)) AS Balance
From TblHeadTrans H, TblTransDetails D, TblAccount A
Where H.guid = D.[LineNo] And D.AccNo = A.AccountNo
And d.[Date] < '01-01-2022' And D.accno = '1003'
Group By D.AccNo, A.AccountName,H.Date,H.TrxNo
) ReportData
WHERE 1=1
Order By AccNo, [Date], TrxNo
and the result showing as the picture:
the result

Count vowels and consonants in an array

I am trying to write a function which will return number of vowels
and consonants. Using the IF statement function will successfully
compile, however when I call it in the select it shows the message :
"Conversion failed when converting the varchar value 'MAMAMIA' to
data type int."`
I tried with the CASE statement, but there are too many syntax
errors and i think it is not the best method of solving the problem
using CASE ...
CREATE FUNCTION VOW_CONS(#ARRAY VARCHAR(20))
RETURNS INT
BEGIN
DECLARE #COUNTT INT;
DECLARE #COUNTT1 INT;
SET #COUNTT=0;
SET #COUNTT1=0;
WHILE (#ARRAY!=0)
BEGIN
IF(#ARRAY LIKE '[aeiouAEIOU]%')
SET #COUNTT=#COUNTT+1
ELSE SET #COUNTT1=#COUNTT1+1
/*
DECLARE #C INT;
SET #C=(CASE #SIR WHEN 'A' THEN #COUNTT=#COUNTT+1;
WHEN 'E' THEN #COUNTT=#COUNTT+1
WHEN 'I' THEN #COUNTT=#COUNTT+1
WHEN 'O' THEN #COUNTT=#COUNTT+1
WHEN 'U' THEN #COUNTT=#COUNTT+1
WHEN 'A' THEN #COUNTT=#COUNTT+1
WHEN ' ' THEN ' '
ELSE #COUNTT1=#COUNTT1+1
END)
*/
END
RETURN #COUNTT;
END
SELECT DBO.VOW_CONS('MAMAMIA')
Without knowing what version of SQL Server you are using, I am going to assume you are using the latest version, meaning you have access to TRANSLATE. Also I'm going to assume you do need access to both the number of vowels and consonants, so a table-value function seems the better method here. As such, you could do something like this:
CREATE FUNCTION dbo.CountVowelsAndConsonants (#String varchar(20))
RETURNS table
AS RETURN
SELECT DATALENGTH(#String) - DATALENGTH(REPLACE(TRANSLATE(#String,'aeiou','|||||'),'|','')) AS Vowels, --Pipe is a character that can't be in your string
DATALENGTH(#String) - DATALENGTH(REPLACE(TRANSLATE(#String,'bcdfghjklmnpqrstvwxyz','|||||||||||||||||||||'),'|','')) AS Consonants --Pipe is a character that can't be in your string
GO
And then you can use the function like so:
SELECT *
FROM (VALUES('MAMAMIA'),('Knowledge is power'))V(YourString)
CROSS APPLY dbo.CountVowelsAndConsonents(V.YourString);
Another option would be to split the string into its individual letters using a tally table, join that to a table of vowels/consonants and then get your counts.
Here is a working example, you'll have to update/change for your specific needs but should give you an idea on how it works.
DECLARE #string NVARCHAR(100)
SET #string = 'Knowledge is power';
--Here we build a table of all the letters setting a flag on which ones are vowels
DECLARE #VowelConsonants TABLE
(
[Letter] CHAR(1)
, [IsVowel] BIT
);
--We load it with the data
INSERT INTO #VowelConsonants (
[Letter]
, [IsVowel]
)
VALUES ( 'a', 1 ) , ( 'b', 0 ) , ( 'c', 0 ) , ( 'd', 0 ) , ( 'e', 1 ) , ( 'f', 0 ) , ( 'g', 0 ) , ( 'h', 0 ) , ( 'i', 1 ) , ( 'j', 0 ) , ( 'k', 0 ) , ( 'l', 0 ) , ( 'm', 0 ) , ( 'n', 0 ) , ( 'o', 1 ) , ( 'p', 0 ) , ( 'q', 0 ) , ( 'r', 0 ) , ( 's', 0 ) , ( 't', 0 ) , ( 'u', 1 ) , ( 'v', 0 ) , ( 'w', 0 ) , ( 'x', 0 ) , ( 'y', 0 ) , ( 'z', 0 );
--This tally table example gives 10,000 numbers
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
SELECT SUM( CASE WHEN [vc].[IsVowel] = 1 THEN 1
ELSE 0
END
) AS [VowelCount]
, SUM( CASE WHEN [vc].[IsVowel] = 0 THEN 1
ELSE 0
END
) AS [ConsonantCount]
FROM [cteTally] [t] --Select from tally cte
INNER JOIN #VowelConsonants [vc] --Join to VowelConsonants table on the letter.
ON LOWER([vc].[Letter]) = LOWER(SUBSTRING(#string, [t].[N], 1)) --Using the number from the tally table we can easily split out each letter using substring
WHERE [t].[N] <= LEN(#string);
Giving you results of:
VowelCount ConsonantCount
----------- --------------
6 10

How to join two aggregate views, when one is a derrived view?

I'm pretty inexperienced with SQL in general, so I'm struggling with this. I know this looks messy and inefficient (so open to suggestions on improving that too!)
I have two queries that are pulling and aggregating data from three different tables. The first query is pulling from a single table, the second is aggregating data from 2 different tables.
SELECT
ifnull( `rt_poes`.`Account`, 'Total Compliant Spend' ) AS `Account`,
round( sum( IF ((( `rt_poes`.`Platform` = 'Google' ) AND ( `rt_poes`.`Ad_Type` = 'Search' )), `rt_poes`.`Cost`, 0 )), 2 ) AS `Compliant Google Search`,
round( sum( IF ((( `rt_poes`.`Platform` = 'Microsoft' ) AND ( `rt_poes`.`Ad_Type` = 'Search' )), `rt_poes`.`Cost`, 0 )), 2 ) AS `Compliant Bing Search`,
round( sum( IF ((( `rt_poes`.`Platform` = 'Google' ) AND ( `rt_poes`.`Ad_Type` = 'Shopping' )), `rt_poes`.`Cost`, 0 )), 2 ) AS `Compliant Google Shopping`,
round( sum( IF ((( `rt_poes`.`Platform` = 'Microsoft' ) AND ( `rt_poes`.`Ad_Type` = 'Shopping' )), `rt_poes`.`Cost`, 0 )), 2 ) AS `Compliant Bing Shopping`,
round( sum( IF ((( `rt_poes`.`Platform` = 'Google' ) AND ( `rt_poes`.`Ad_Type` = 'Search' )), `rt_poes`.`Cost`, 0 )), 2 ) +
round( sum( IF ((( `rt_poes`.`Platform` = 'Microsoft' ) AND ( `rt_poes`.`Ad_Type` = 'Search' )), `rt_poes`.`Cost`, 0 )), 2 )
AS `Compliant Country Spend`
FROM
`rt_poes`
WHERE
((
`rt_poes`.`field1` LIKE '% condition1%'
)
OR ( `rt_poes`.`field2` LIKE '% condition2%' )
GROUP BY
`rt_poes`.`Account` WITH ROLLUP
ORDER BY
sum( `rt_poes`.`Cost` )
This works well and generates a nice overview of the data I'm looking for as below.
The second query is:
SELECT ifnull( Account, 'Total All Platform Spend' ) AS Account, Round(SUM(Cost), 2) AS total_platform_costs
FROM
(SELECT Account, Cost FROM QTD_Account_Report
UNION ALL
SELECT AccountName, Spend FROM Bing_QTD_Account_Report) AS DerivedTable
GROUP BY DerivedTable.Account WITH ROLLUP
ORDER BY total_platform_costs
This generates another nice view of the data from another table that I'm looking for too.
The output of both is correct.
Now, I'm trying to join both on the account column. Essentially just add the second column from the second output on to the output of the first query.
The problem I'm having is that whenever I try to use a standard join, I get an error that MySQL does not support this syntax.
Is there another way to join the two or modify the second so that I can have a single view with both like below? Or do I have to create a whole new table for this?
I haven’t done MySQL in a while, but simply joining the second query should work. Is this what you did?
select
ifnull(rt_poes.Account, 'Total Compliant Spend') as Account,
round( sum( if(rt_poes.Platform = 'Google' AND rt_poes.Ad_Type = 'Search', rt_poes.Cost, 0)), 2) as `Compliant Google Search`,
round( sum( if(rt_poes.Platform = 'Microsoft' AND rt_poes.Ad_Type = 'Search', rt_poes.Cost, 0)), 2) as `Compliant Bing Search`,
round( sum( if(rt_poes.Platform = 'Google' AND rt_poes.Ad_Type = 'Shopping', rt_poes.Cost, 0)), 2) as `Compliant Google Shopping`,
round( sum( if(rt_poes.Platform = 'Microsoft' AND rt_poes.Ad_Type = 'Shopping', rt_poes.Cost, 0)), 2) as `Compliant Bing Shopping`,
round( sum( if(rt_poes.Platform = 'Google' AND rt_poes.Ad_Type = 'Search', rt_poes.Cost, 0)), 2) +
round( sum( if(rt_poes.Platform = 'Microsoft' AND rt_poes.Ad_Type = 'Search', rt_poes.Cost, 0)), 2) as `Compliant Country Spend`
round(SUM(DerivedTable.Cost), 2) as total_platform_costs
from rt_poes
left join (select Account, Cost
from QTD_Account_Report
UNION ALL
select AccountName, Spend
from Bing_QTD_Account_Report) as DerivedTable on DerivedTable.Account = rt_poes.Account
where rt_poes.field1 like '%condition1%' or rt_poes.field2 like '%condition2%'
group by rt_poes.Account WITH ROLLUP
order by sum(rt_poes.Cost)
It would be helpful if you quoted the specific error message you got, as well as the query that caused it.

MySQL equivalent in MSSQL to assigning a variable and using it

I tried finding the answer, but maybe I am too new to MSSQL, I come from MySQL, so this is my question super simplified to go straight to the point:
Imagine we have a table "Things"
Thingie | Value
--------+-------
Thing1 | 10
Thing1 | 15
Thing1 | 16
In MySQL I could do something like this in a query:
SET #halfvalue := 0;
SELECT Thingie, Value,
(#halfvalue := Value / 2) AS HalfValue,
(#halfvalue / 2) AS HalfOfHalf
FROM Things
Which would return
Thingie | Value | HalfValue | HalfofHalf
--------+-------+-----------+------------
Thing1 | 10 | 5.00 | 2.50
Thing1 | 15 | 7.50 | 3.75
Thing1 | 16 | 8.00 | 4.00
Looks pretty simple, the actual one is a tad more complicated.
My problem is, in MSSQL I can't assign, and use a variable on the same SELECT. And I can't find anything similar to this functionality on this simple level.
Any solutions?
Edit, this is the select that contains all those nasty operations:
SELECT
fvh.DocEntry,
MAX( fvs.SeriesName ) AS "Serie",
MAX( fvh.DocNum - 1000000 ) AS "Número",
MAX( fvh.DocDate ) AS "Fecha",
MAX( fvh.U_FacNit ) AS "NIT",
MAX( fvh.U_FacNom ) AS "Nombre",
MAX( IIF( ISNULL( fvh.Address, '' ) = '', fvh.Address2, fvh.Address ) ) AS "Dirección",
SUM( fvd.GTotal - ISNULL( ncd.GTotal, 0 ) ) AS "Total",
IIF( MAX( fvh.CANCELED ) = 'Y' OR ( SUM( fvd.GTotal - ISNULL( ncd.GTotal, 0 ) ) = 0 ),
'Anulada',
IIF( SUM( fvd.GTotal ) > SUM( ISNULL( ncd.GTotal, 0 ) ) AND ( SUM( ISNULL( ncd.GTotal, 0 ) ) > 0 ),
'Devuelta',
'Emitida' )
) AS "Estado",
ROUND( ( ( SUM( fvd.GTotal - ISNULL( ncd.GTotal, 0 ) ) / 1.12 ) * 0.12 ), 4 ) AS "IVA",
ROUND( SUM( IIF( fvd.U_TipoA = 'BB',
( fvd.GTotal - ISNULL( ncd.GTotal, 0 ) ) - ( ( ( fvd.GTotal - ISNULL( ncd.GTotal, 0 ) ) / 1.12 ) * 0.12 ),
0 ) ), 4) AS "Bien",
ROUND( SUM( IIF( fvd.U_TipoA = 'S',
( fvd.GTotal - ISNULL( ncd.GTotal, 0 ) ) - ( ( ( fvd.GTotal - ISNULL( ncd.GTotal, 0 ) ) / 1.12 ) * 0.12 ),
0 ) ), 4) AS "Servicio",
ROUND( SUM( IIF( fvd.U_TipoA = 'N',
( fvd.GTotal - ISNULL( ncd.GTotal, 0 ) ) - ( ( ( fvd.GTotal - ISNULL( ncd.GTotal, 0 ) ) / 1.12 ) * 0.12 ),
0 ) ), 4) AS "No Aplica",
COUNT(fvd.LineNum) AS "Lineas", SUM(fvd.GTotal) AS "FCTotal",
SUM(ISNULL( ncd.GTotal, 0 )) AS "NCTotal"
/* Facturas */
FROM OINV AS fvh
LEFT JOIN NNM1 AS fvs ON fvs.Series = fvh.Series
LEFT JOIN INV1 as fvd ON fvd.DocEntry = fvh.DocEntry
/* Notas de Credito */
LEFT JOIN RIN1 AS ncd ON ncd.BaseEntry = fvh.DocEntry AND ncd.LineNum = fvd.LineNum
WHERE fvh.DocDate BETWEEN ? AND ? /*AND fvh.DocEntry = 1108*/
GROUP BY fvh.DocEntry
Thank you all for your time. I will dismantle my query and re-do it taking into consideration all of your input. Gracias, totales.
You think you can do this in MySQL:
SET #halfvalue := 0;
SELECT Thingie, Value,
(#halfvalue := Value / 2) AS HalfValue,
(#halfvalue / 2) AS HalfOfHalf
FROM Things;
But you are wrong. Why? MySQL -- as with every other database -- does not guarantee the order of evaluation of expression in a SELECT. The documentation even warns about this:
In the following statement, you might think that MySQL will evaluate #a first and then do an assignment second:
SELECT #a, #a:=#a+1, ...;
However, the order of evaluation for expressions involving user variables is undefined.
In both databases, you can use a subquery. In the most recent versions of MySQL (and just about any other database), you can also use a CTE:
SELECT Thingie, Value, HalfValue,
(HalfValue / 2) AS HalfOfHalf
FROM (SELECT t.*, (Value / 2) AS HalfValue
FROM Things t
) t;
The answer is simple: you can't do that in MSSQL, because when you try it you'll get:
Msg 141, Level 15, State 1, Line 3
A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations.
which you most probably experienced.
The most simple workaround would be:
SELECT Thingie, Value, Value/2, Value/4 from Things
Other method:
select Thingie, Value, HalfValue, HalfValue / 2 from (
SELECT Thingie, Value, Value / 2 HalfValue from Things
) a
No, that doesn't work in SQL. The parameter value is not set until the query completes. You can do it in two steps:
DECLARE #halfvalue FLOAT = 0;
SELECT #halfvalue = ([Value] / 2)
FROM Things ;
SELECT Thingie
, [Value]
, HalfValue = [Value]/2
, HalfAgainValue = #halfvalue / 2
FROM Things ;

mysql matching multiple and's and or's

I am trying to get rows from a table where there are matches on multiple other tables.
This is the query I am running.
SELECT qt.*, DATEDIFF(CURRENT_DATE, STR_TO_DATE(up.DOB, '%m-%d-%Y')) / 365 AS Age
FROM UserProfile AS up, Game AS g, QuestionTable AS qt
WHERE NOT EXISTS(SELECT * FROM Options WHERE UserID = 75 AND QID = qt.QID AND DateTime >= CURDATE())
AND g.Active = 1 AND g.QID = qt.QID
AND (((g.Gender = up.Gender OR g.Gender = 'B') AND ((g.City = up.City AND g.Zip = up.Zip AND g.Country = up.Country) OR g.Home = 0) AND ((Age BETWEEN g.Maximum AND g.Minimum) OR g.Age = 0) AND ((SQRT( POW( 69.1 * ( g.Latitude - -93.5746359 ) , 2 ) + POW( 69.1 * ( 44.9737707 - g.Longitude ) * COS( g.Latitude / 57.3 ) , 2 ) ) > g.Distance) OR g.Geo = 0)) OR g.Special = 0)
GROUP BY qt.QID
I have ran this expression through C# and it returns true, yet it is only matching on the 'g.Special = 0' part through MySql.
Any help on this would be much appreciated!
Resolved the issue by fixing some mistakes I made and changed the query to this,
SELECT *
FROM QuestionTable AS qt
WHERE NOT EXISTS
(SELECT * FROM Options WHERE UserID = 75 AND QID = qt.QID AND DateTime >= CURDATE())
AND EXISTS(SELECT g.* FROM UserProfile AS up, Game AS g WHERE g.Active = 1 AND g.QID = qt.QID AND(g.Special = 0 OR(
(g.Gender = up.Gender OR g.Gender = 'B') AND
((g.City = up.City AND g.zip = up.Zip AND g.Country = up.Country) OR g.Home = 0) AND
((SQRT( POW( 69.1 * ( g.Latitude - 44.9737707 ) , 2 ) + POW( 69.1 * ( -93.5746359 - g.Longitude ) * COS( g.Latitude / 57.3 ) , 2 ) ) < g.Distance) OR g.Geo = 0) AND
((DATEDIFF(CURRENT_DATE, STR_TO_DATE(DOB, '%m/%d/%Y'))/365.25 BETWEEN g.Minimum AND g.Maximum) OR g.Age = 0))))