Is there an easier way than nested iifs to count mismatched conditions in SQL server - sql

The picture below shows a table of accounts and the outcomes that I want to count. Ie every time the account number is 106844 and the outcome is "MESSAGE" or "ESCALATION EMAIL" that should count as 1 where any other outcome counts as 0. What I would normally do is a horrible mess of iifs like
sum( iif([account] = '106719' and [Outcome] in ('MESSAGE','ESCALATION_EMAIL'),1,iif([account] = '310827' and [outcome] <> 'ABORT' and 'CALL_OUTCOME_LB' in ("Call patched to Customer Care","Message Taken"),1,iif( ... , 0) as [Total Outcomes]
and so on but man it feel like there's got to be an easier way or one less prone to making a random mistake in the 7th nested iif and messing the whole thing up. Any ideas?

Don't use iif(). It is a function brought into SQL Server for back-compatibility to MS ACCESS. Why would you want to be backwards compatible to such a thing?
Use the ANSI standard CASE expression:
sum(case when account = '106719' and Outcome in ('MESSAGE', 'ESCALATION_EMAIL')
then 1
when account = '310827' and outcome <> 'ABORT' and
'CALL_OUTCOME_LB' in ("Call patched to Customer Care", "Message Taken")
then 1
. . .
else 0
end) as Total_Outcomes
I would also advise you to name your columns so they don't need to be escaped (why "Total Outcomes" became "Total_Outcomes"). That simplifies the code.

Why not use a lookup table that has the Account and Outcome and use that? Then, as requirements change, you could update the lookup table and not worry about your code.

Yeah... there is
The last parameter is for when the condition is false, everything else will fall in there.
SUM( IIF([ACCOUNT] = '106719' AND [OUTCOME] IN ('MESSAGE','ESCALATION_EMAIL'),1,0))

Related

CASE statements - Making the THEN display information from another column

Good morning All,
I had a question regarding case statements. Let me set up a scenario that I am having a hard time with. Say we have a table with all of our providers licenses. Each provider can have anywhere from one to a number of licenses. I want to create a case statement that says basically WHEN the providers license type equals this, then display the license number from this different column holding the values for their numbers.
Hope this makes sense. I do not want it to display words such as THEN 'Primary Care Physician' , instead would like it to provide the actual license number in the THEN.
Any ideas? Thank you!
Just use the CASE syntax as it is described in the documentation: https://www.postgresql.org/docs/7.4/static/functions-conditional.html
CASE WHEN license_type = 1 THEN license_number_column_a
WHEN license_type = 2 THEN license_number_column_b
END
I Fugere that you are trying to use a code like
Case licence_type
when 1 then licence_number_column_a
when 2 then licence_number_column_b
...
End
This type of Case works exclusively when you are evaluating constants.
When you are evaluating columns, you need to move the test to "when"
Case
when licence_type = 1 then licence_number_column_a
when licence_type = 2 then licence_number_column_b
...
End

How do I increase a counter by 1 for each repeated value?

As part of my course in university I have to make a database in Microsoft Access which is somewhat limiting me on what I'm trying to do. I have a table that has the information of whether a player in a team was present for a fixture or not using the values "P", "R", and "M" (Played, Reserves, Missed). I want to make a query that counts a value of 1 for each value of P or R and a separate one for M, so that when I make a report that prints off a membership card, it shows the amount of fixtures they've played in and the amount of fixtures that they have missed.
Sorry if this isn't clear, I'll try to explain myself further if you ask but I'm not very good with this stuff. Thank you.
Edit: I'll use screenshot links if that's okay, here is the Fixture Attendance entity that shows if a member of a team attended a game or not. I'm making a membership card based off this one. I want to be able to display the No. of fixtures played by the member and the No. of fixtures missed based off the values in the above entity and use that information in a form I'm going to create. That will be a subform inside my Membership Card form.
I'm presumably really bad at explaining this - I understand Access is rarely used in the real world so I'm not sure why I'm doing this in the first place and don't feel like I'm getting any real knowledge of working with databases.
You should use the COUNT function.
http://office.microsoft.com/en-us/access-help/count-data-by-using-a-query-HA010096311.aspx
I am guessing that you want something like this:
select playerid, sum(iif(fixture in ("P", "R"), 1, 0)) as NumPR,
sum(iif(figure = "M", 1, 0)as NumM
from table t
group by playerid;
The key idea here is putting the conditional part (iif()) inside the sum().
CASE WHEN can be used to translate the codes into 1's and 0's. Then use SUM with a GROUP BY to sum them.
SELECT player_id, SUM(Played), SUM(Reserve), SUM(Missed)
FROM
(SELECT player_id,
CASE WHEN present = 'P' THEN 1 ELSE 0 AS Played,
CASE WHEN present = 'R' THEN 1 ELSE 0 AS Reserve,
CASE WHEN present = 'M' THEN 1 ELSE 0 AS Missed
FROM fixtures)
GROUP BY player_id;

sql server group by with an alias

I am new to sql server, transitioning from mysql.
I have a complicated case statement that I would like to group on 6 whens and an else. Likely to get larger. To be able to run it, I need to copy the statement into the group by each time there is a modification. In mySql I would just group by the column number. Is there any work around for this? Making the code very ugly.
Is there going to be a performance penalty in creating a sub query for my case, then just grouping on the result field. Seems like trying to make the code more elegant will cause the query to use more resources.
Thanks
Below is a field I am grouping on. As I make a modification to the field for more edge cases, then I need to change code in up to 3 places. Makes for some very ugly code, and I need no extra help doing that myself.
dz_code = case
when isnull(dz.dz_code,'N/A') in ('GAB', 'MAB', 'N/A') and dc.howdidyouhear = 'Television' then 'Television'
when isnull(dz.dz_code,'N/A') in ('GAB', 'MAB', 'N/A') and dc.howdidyouhear in ('Other', 'N/A') then 'Other'
WHEN dz.dz_code = 'irs,irs' THEN 'irs'
when dz.dz_code like '%SDE%' THEN 'SDE'
when dz.dz_code like 'referral,' then REPLACE(dz.dz_code, 'referral','')
when charindex(',',dz.dz_code) = 4 then left(dz.dz_code,3)
else
dz.dz_code
END,
Maybe you can wrap the query in a subquery and use the alias in the select and the group by. It looks a little bulky in this example, but if you've got more complex case switches, or more than one of them, then this solution will probably much smaller and more readable.
select
CaseField
from
(select
case when 1 = 2 then
3
else 4 end as CaseField
from
YourTable t) c
group by
CaseField

Is there a way to use the condition of an If statement as its value?

This could be a simple question, but it's one I've never seen answered before. Is there a way to use an if statement's condition as its value? This would be really useful in cases where lots of calculation is done to determine if a certain condition is met and if it is, that calculation is the result.
As an example:
if ( [intense calculation] > 0, [same intense calculation], 0)
I'm interested particularly with regards to SQL, as I'm working on a report in Access right now and so can't store the result of the intense calculation in a variable.
Not sure if such a concept exists in the MS Access report world, but how about:
MAX([intense calculation], 0)
The obvious benefit of such an approach is that the calculation would only need to be done once.
One approach in most forms of SQL would be to move the main query to a sub-query, with the intense calculation column aliased and tested in the new outer query - like so:
select v.*,
case intense_calc > 0 then intense_calc else 0 end as positive_calc
from (select [intense calculation] as intense_calc,
[other columns]
from ...) as v

Sql custom statement

What is the Programme for Sql data in Microsoft Expression Web Custom Statement similar to following Access database statement:
Sum(IIf([accident]![Rly]='CR',1,0))
Im not sure you will be able to use this format as this will run against each individual row and always return 1 or 0. To run against your whole query to get the total sum you need something similar to this:
SELECT SUM(Rly) FROM
(SELECT ID, CASE WHEN Accident.Rly = 'CR' THEN 1 ELSE 0 END Rly
FROM Accident)
The syntax may be slightly different but hopefully this will set you in the right direction.