Query for Excel or DB2 - sql

How can I write this as formula in Excel, and also how to use this logic in DB2 query :
IF:
Month(max(A_dt)) <= month(B_dt)
that is being used
THEN:
day=01, month=month(A_dt), year=year(B_dt) + 1
ELSE:
day=01 Month=Month(A_dt) Year=Year(B_dt)

This question is quite vague and hard to answer without any idea of table structure and data set. Following the logic that you outline, year is the only output that changes based on the conditional.
The below contains three simple case statements to handle your conditional. The first two are completely pointless due to returning the same response no matter pass or fail (per your logic above), but I included them still just to illustrate the point as it may help you understand if the conditional is confusing you.
I would suggest reading up on the db2 manual for your specific flavor or doing some intro sql tutorials. The case is pretty fundamental and quite useful in query writing.
select
_key
,case when month(max(a_dt)) <= month(b_dt)
then 01
else 01
end as day
,case when month(max(a_dt)) <= month(b_dt)
then month(a_dt)
else month(a_dt)
end as month
,case when month(max(a_dt)) <= month(b_dt)
then year(b_dt) + 1
else year(b_dt)
end as year
from
your_table

Related

How to add a value to this SQL statement in DB2?

I need to add 'P06' to the case where the subquery is selecting RPCODE. I'm still learning about SQL so I'm still not an expert at subqueries so I'm not exactly sure how to add a value to the statement.
My first solution was just to add OR 'P06' after 'P01', but that doesn't seem right.
CASE WHEN (SELECT RPCODE FROM AGQA.QAB2010
WHERE INDATE || INTIME = ( SELECT MAX(INDATE||INTIME) FROM AGQA.QAB2010 WHERE RTAG IN (SELECT TAG FROM TAGDATA) )
AND RTAG IN (SELECT TAG FROM TAGDATA) ORDER BY RPDATE DESC, SER DESC FETCH FIRST 1 ROW ONLY) = 'P01' THEN 'N' ELSE 'C' END
ELSE 'R' END, 'S' ) AS TTYPE
Right now, when the RPCODE is 'P01', the TTYPE shows as 'N'. I need to add 'P06' so that the TTYPE will show as 'N' for RPCODE 'P06' as well
As Rob Wilson commented...
Change the = 'P01' to IN ('P01', 'P06')
However, while the statement may work for you, performance over a dataset of any decent size is probably going to suck.
The number of sub-select's and fetch first row are red flags to my eye.
With a background in RPG development on Db2 for i, the statement looks like many I've seen from RPG programmers used to working with data 1 record at a time rather than working with sets of data.
But the same "row by agonizing row" (RBAR as coined by Jeff Moden of SqlServerCentral.com) processing can be seen in SQL from developers on any platform and from any background.
Unfortunately, moving to a set base process isn't a quick fix for non-trivial statements. The complete statement and detailed information about the data and the table design is needed.

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

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))

SQL Case inside WHEN

May be this is silly but can we write a case inside another case's WHEN?
Below code working for me but I am not sure if this is correct.
SELECT
(SUM(CASE
WHEN (
CASE
WHEN r.status < b.status
THEN r.status
ELSE b.status
END
) = '4'
THEN 1
ELSE 0
END)
) AS WORKED
FROM
tbl1 r, tbl2 b
All the examples on nested cases are like CASE inside a THEN so I am not sure if this a good practice. Is there a better way to get the same results?
Yes you can. MSDN also informs us that in SQL SERVER, you can only have a maximum of 10 CASE expressions embedded into each other. Oddly enough, a search for ORACLE up negative about this potential limitation. Probably important to note.
Of course, you can also just use more WHEN (up to 255 in ORACLE) statements, too, but that only works if you do not need to nest your logic (such as comparing two different columns values)
Sources:
https://msdn.microsoft.com/en-us/library/ms181765.aspx
http://www.techonthenet.com/oracle/functions/case.php

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

SQL query exlude data between date and also matching another condition

All,
First time poster on here. I am trying to create a query where I want to exclude data between a date range but also having certain codes.
Date:
(substring(CAST(UTCBigintToUTCTime(starttime) as varchar(19)),0,11) not between '2012-05-08%' and '2012-05-10%
Status Code:
statuscode NOT IN ('58','59'))
What would my statement look like to exclude data that meets BOTH of those conditions? Everything I do excludes all in that date range and all in the status code range.
Thanks in advance. SQL newbie but learning :).
It seems to me that you're over-thinking it a bit, and making it more complex than it needs to be.
And making it this complex, especially with negative logic, will also make it perform poorly.
How about something like:
select * from myTable where starttime < '2012-05-08' and starttime > '2012-05-10' and statuscode < 58 and statuscode > 59
Not sure what database you are using, or exactly what your data types are - adjust slightly as necessary, but try to stay away from nasty date/string conversions and 'NOT' conditions wherever possible.
try this
select * from myTable where convert(date,starttime) not between '2012-05-08' and '2012-05-10' and statuscode not in (58,59)
and let me know.