Access SQL IF statement failing - sql

Whats wrong with this IF statement? It appears to follow the criteria for a IF, but will not run
SELECT Account, SUM(IF dbo_ADT.type = "wager"
AND - dbo_ADT.amount > 0 then - dbo_ADT.amount
ElseIf dbo_ADT.type = "cancel" THEN
- dbo_ADT.amount elseIf dbo_ADT.type = "winnings"
THEN - dbo_ADT.refund ELSE 0 END IF) AS Handle
FROM dbo_ADT

Access SQL does not support the if...then...elsesyntax (in sql, it's of course supported in vba) but you can use the iif(condition, "value if true", "value if false") to accomplish the same thing if you nest the iifstatements. I think your query should be written as:
SELECT
Account,
SUM(
IIF(
dbo_ADT.type = "wager" AND - dbo_ADT.amount > 0,
- dbo_ADT.amount,
IIF(
dbo_ADT.type = "cancel",
- dbo_ADT.amount,
IIF(dbo_ADT.type = "winnings", dbo_ADT.refund, 0)
)
)
) AS Handle
FROM dbo_ADT
GROUP BY Account
I might have mixed up the nesting (although I believe it's correct), so you'll have to check that you get the expected result (especially for the else condition), but you should get the idea I hope.
I also added a group byclause that's needed when you use aggregate functions.

Related

Syntax error in CASE expression, unable to rectify

I want below code in my where condition:
Condition statement is like :
ONE DAY PRIOR TO RENEWAL,
Policy has the Newly Independent Discount (RAP16.DSCCD = '366' exists)
AND
AT RENEWAL,
The Newly Independent discount drops (RAP16.DSCCD = '366' dropped)
I tried below code
AND case when tt.ja2_effdt_t = rap01.hmedt_t - 1
then trim(RAP16.DSCCD) = '366'
when trim(rap01.hmedt_t) <> tt.ja2_effdt_t)
then trim(RAP16.DSCCD) <> '366'
end
There is some syntax error in below code, But I am unable to rectify it.
It's generally better to use AND/OR constructions instead of case expressions in the WHERE clause. You probalby want something like:
AND ((tt.ja2_effdt_t = rap01.hmedt_t - 1 AND trim(RAP16.DSCCD) = '366')
AND
(trim(rap01.hmedt_t) <> tt.ja2_effdt_t AND trim(RAP16.DSCCD) <> '366'))

how do I join two tables sql

I have an issue that I'm hoping you can help me with. I am trying to create charting data for performance of an application that I am working on. The first step for me to perform two select statements with my feature turned off and on.
SELECT onSet.testName,
avg(onSet.elapsed) as avgOn,
0 as avgOff
FROM Results onSet
WHERE onSet.pll = 'On'
GROUP BY onSet.testName
union
SELECT offSet1.testName,
0 as avgOn,
avg(offSet1.elapsed) as avgOff
FROM Results offSet1
WHERE offSet1.pll = 'Off'
GROUP BY offSet1.testName
This gives me data that looks like this:
Add,0,11.4160277777777778
Add,11.413625,0
Delete,0,4.5245277777777778
Delete,4.0039861111111111,0
Evidently union is not the correct feature. Since the data needs to look like:
Add,11.413625,11.4160277777777778
Delete,4.0039861111111111,4.5245277777777778
I've been trying to get inner joins to work but I can't get the syntax to work.
Removing the union and trying to put this statement after the select statements also doesn't work. I evidently have the wrong syntax.
inner join xxx ON onSet.testName=offset1.testName
After getting the data to be like this I want to apply one last select statement that will subtract one column from another and give me the difference. So for me it's just one step at a time.
Thanks in advance.
-KAP
I think you can use a single query with conditional aggregation:
SELECT
testName,
AVG(CASE WHEN pll = 'On' THEN elapsed ELSE 0 END) AS avgOn,
AVG(CASE WHEN pll = 'Off' THEN elapsed ELSE 0 END) AS avgOff
FROM Results
GROUP BY testName
I just saw the filemaker tag and have no idea if this work there, but on MySQL I would try something along
SELECT testName, sum(if(pll = 'On',elapsed,0)) as sumOn,
sum(if(pll = 'On',1,0)) as numOn,
sum(if(pll ='Off',elapsed,0)) as sumOff,
sum(if(pll ='Off',1,0)) as numOff,
sumOn/numOn as avgOn,
sumOff/numOff as avgOff
FROM Results
WHERE pll = 'On' or pll='Off'
GROUP BY testName ;
If it works for you then this should be rather efficient as you do not need to join. If not, thumbs pressed that this triggers another idea.
The difficulty you have with the join you envisioned is that the filtering in the WHERE clause is performed after the join was completed. So, you would still not know what records to use to compute the averages. If the above is not implementable with FileMaker then check if nested queries work. You would then
SELECT testName, on.avg as avgOn, off.avg as avgOff
FROM ( SELECT ... FROM Results ...) as on, () as off
JOIN on.testName=off.testName
If that is also not possible then I would look for temporary tables.
OK guys... thanks for the help again. Here is the final answer. The statement below is FileMaker custom function that takes 4 arguments (platform, runID, model and user count. You can see the sql statement is specified. FileMaker executeSQL() function does not support nested select statements, does not support IF statements embedded in select statements (calc functions do of course) and finally does not support the SQL keyword VALUES. FileMaker does support the SQL keyword CASE which is a little more powerful but is a bit wordy. The select statement is in a variable named sql and result is placed in a variable named result. The ExecuteSQL() function works like a printf statement for param text so you can see the swaps do occur.
Let(
[
sql =
"SELECT testName, (sum( CASE WHEN PLL='On' THEN elapsed ELSE 0 END)) as sumOn,
sum( CASE WHEN PLL='On' THEN 1 ELSE 0 END) as countOn,
sum( CASE WHEN PLL='Off' THEN elapsed ELSE 0 END) as sumOff,
sum( CASE WHEN PLL='Off' THEN 1 ELSE 0 END) as countOff
FROM Results
WHERE Platform = ?
and RunID = ?
and Model = ?
and UserCnt = ?
GROUP BY testName";
result = ExecuteSQL ( sql ; "" ; ""
; platform
; runID
; model
; userCnt )
];
getAverages ( Result ; "" ; 2 )
)
For those interested the custom function looks like this:
getAverages( result, newList, pos )
Let (
[
curValues = Substitute( GetValue( data; pos ); ","; ¶ );
sumOn = GetValue( curValues; 2 ) ;
countOn = GetValue( curValues; 3 );
sumOff = GetValue( curValues; 4 );
countOff = GetValue( curValues; 5 );
avgOn = sumOn / countOn;
avgOff = sumOff / countOff
newItem = ((avgOff - avgOn) / avgOff ) * 100
];
newList & If ( pos > ValueCount( data); newList;
getAverages( data; If ( not IsEmpty( newList); ¶ ) & newItem; pos + 1 ))
)

Qlikview expression not affected by selection EXCEPT two specific fields

I have a Qlikview expression that I want it to not be affected by any selections EXCEPT two specific fields: Year & Month.
My Expression is:
Sum(Aggr(IF(Duration = 0.5 , 0.5,
IF(DayName = 'Sat',0,
IF(DayName = 'Sun',0,
RangeSum(
Count({<Key = {"=Len(Trim([Date From])) > 0"}>}DISTINCT Name),
Avg({<Key = {"=Len(Trim([Date From])) = 0"}>}0))))), Name, ADate))
I know you can use something like; {1<Year = $:: Year>} & {1<Month = $:: Month>} to accomplish this but I cant quite get it right.
There's a few ways to accomplish this, but if you're sure you want the expression to consider only the two fields you mentioned, I like to start with the total set of all data and filter to just the ones you want.
You are basically there, depending on what expression you want restricted you'd use {1<Year = $:: Year>} or {1<Month = $:: Month>} like you said in any place you want restricted. The 1 set identifier will start with the total set of all data in the application, then the set modifiers, Year and Month will be set based on selection in the default state designated by the $ set identifier.
So something like this should work I think:
Sum({1<Year=$::Year, Month=$::Month>}
Aggr(
IF( Duration = 0.5 , 0.5,
IF(DayName = 'Sat', 0,
IF(DayName = 'Sun', 0,
RangeSum({
Count({<Key = {"=Len(Trim([Date From])) > 0"}>} DISTINCT Name),
Avg({<Key = {"=Len(Trim([Date From])) = 0"}>} 0 )
)
)
)
),
Name, ADate)
)
You may have to add this to your count and avg expressions as well.
I am confused about this expression: Avg({<Key = {"=Len(Trim([Date From])) = 0"}>} 0 ). It is averaging 0. Is that right?

Nhibernate query condition within sum

I am trying the following code but nhibernate is throwing the following exception:
Expression type 'NhSumExpression' is not supported by this SelectClauseVisitor.
var data =
(
from a in session.Query<Activity>()
where a.Date.Date >= dateFrom.Date && a.Date.Date <= dateTo.Date
group a by new { Date = a.Date.Date, UserId = a.RegisteredUser.ExternalId } into grp
select new ActivityData()
{
UserID = grp.Key.UserId,
Date = grp.Key.Date,
Bet = grp.Sum(a => a.Amount < 0 ? (a.Amount * -1) : 0),
Won = grp.Sum(a => a.Amount > 0 ? (a.Amount) : 0)
}
).ToArray();
I've been looking around and found this answer
But I am not sure what I should use in place of the Projections.Constant being used in that example, and how I should create a group by clause consisting of multiple fields.
It looks like your grouping over multiple columns is correct.
This issue reported in the NHibernate bug tracker is similar: NH-2865 - "Expression type 'NhSumExpression' is not supported by this SelectClauseVisitor."
Problem is that apart from the less-than-helpful error message, it's not really a bug as such. What happens in NH-2865 is that the Sum expression contains something which NHibernate doesn't know how to convert into SQL, which result in this exception being thrown by a later part of the query processing.
So the question is, what does you sum expression contains that NHibernate cannot convert? The thing that jumps to mind is the use of the ternary operator. I believe the NHibernate LINQ provider has support for the ternary operator, but maybe there is something in this particular combination that is problematic.
However, I think your expressions can be written like this instead:
Bet = grp.Sum(a => Math.Min(a.Amount, 0) * -1), // Or Math.Abs() instead of multiplication.
Won = grp.Sum(a => Math.Max(a.Amount, 0))
If that doesn't work, try to use a real simple expression instead, like the following. If that works, we at least know the grouping itself work as expected.
Won = grp.Sum(a => a.Amount)

SQL - Trouble with simple select query

I'm having some trouble figuring out why the SQL query below isn't working ... when members_only is set to 0, it's still showing them...
SELECT *
FROM reports
WHERE story = "1"
OR barebones = "1"
AND members_only = "1"
It depends on your data, but you may not be aware that AND has higher precedence in SQL than OR, so your query really evaluates to this:
SELECT *
FROM reports
WHERE story = '1'
OR (barebones = '1' AND members_only = '1')
Consider using different brackets per the other answers to explicitly declare your intentions
Use brackets to distinguish your clarify the WHERE-condition.
SELECT *
FROM reports
WHERE (story = '1' OR barebones = '1')
AND members_only = '1'
I would say because it reads the query as:
WHERE (story = '1') OR (barebones = '1' AND members_only = '1')
since story = '1', the condition is satisfied
OR clauses can be tricky - you often need to explicitly tell the query where it belongs. I assume, you want this:
WHERE (story = '1' OR barebones = '1') AND members_only = '1'
Missing parenthesis?
Did you want to do something like this:
SELECT *
FROM reports
WHERE (story = "1" OR barebones = "1") AND members_only = "1"
You are missing parenthesis.
The following code will work, assuming members_only HAS to be "1", but only story or barebones has to be "1".
SELECT *
FROM reports
WHERE
(story = "1" OR barebones = "1")
AND members_only = "1"
You should read up on TSQL Operator Precedence
In your original code, assume the following:
store = 1
barebones = 1
*members_only* = 0
Due to Operator Precedence, barebones and *members_only* is evaluated first, and evaluates to false.
Following this, the result of the first boolean evaluation (false) (also known as The Right Side) is compared to (story = "1") (also known as The Left Side).
The Right Side evaluates to false, but The Left Side evaluates to true.
Since the final boolean compression uses the OR operator, the end result is a TRUE, thus that record is indeed returned, no matter the value of either barebones or *members_only*, since The Left Side always evaluates to True.