SQL Server Return Null if exists - sql

In SQL Server 2008 I am looking to create a query that will return a NULL in an aggregate if one exists, otherwise I'm looking for the maximum. This is a simplified example...
I have the following data:
CO Loc Term_Dt
1 A 7/15/2013
1 B
1 C 10/30/2000
2 A 8/10/2008
2 B 6/1/2015
2 C 4/30/2010
The result I'm looking for is:
CO Term_Dt
1 NULL
2 6/1/2015
because technically the Company is still open if at least one location has not yet been terminated.
Thanks

Just use aggregation and a case statement:
select co,
(case when count(term_dt) = count(*) then max(term_dt)
end) as term_dt
from table t
group by co;
count(<column>) counts the number of non-NULL values. If this doesn't match all the rows, then at least one is NULL. No else is needed for the case, because the default is NULL.

Generate a sub set of data with companies having null term dates and left join your super set to it. Any records in 2nd table which are not null you want to display as null so use a case statement.
This works because our outer table (A) returns
CO TERM_DT
1 7/15/2013
2 6/1/2015
But then our LEFT join on our inline view also adds B.Co...
CO TERM_DT B.CO
1 7/15/2013 1
2 6/1/2015 NULL
So you can see by saying we want to display NULL when B.CO is not null instead of the max(TERM_DT) will yield the desired results. This is accomplished using a case statement.
SELECT A.Co,
Case when B.CO is not null then Max(A.Term_DT) else NULL end as Term_DT
FROM tableName A
LEFT JOIN (SELECT Distinct CO from tableName where Term_dt is null) B
on A.Co = B.CO
GROUP BY CO

Related

Join two tables on multiple conditions Using Oracle SQL

I have a 2 Tables with below structures
Table 1-- Containing Values like this.
OTHER_CODE
CAPACITY_CODE
Result
A
1
A
5
A
9
A
(null)
B
2
B
6
B
2
Table_2- With Values Like
OTHER_CODE
CAPACITY_CODE
Result
A
1
A
A
5
B
A
(null)
C
A
ELSE
D
B
ALL
E
(null)
ALL
F
I need to Join Table_1 with Table_2 on basis of columns OTHERCODE and CAPACITYCODE and update values in Column Result of Table**1 **using a Merge statement.
I need to handle and match Values based on ELSE and ALL values too.
Check for Direct Match
Check if ALL or ELSE condition
The Final TABLE_1 must look like
OTHER_CODE
CAPACITY_CODE
Result
Explanation
A
1
A
Direct Join
A
5
B
Direct Join
A
9
D
Satsifying ELSE condition
A
(null)
C
Direct join with NVL handling
B
2
E
As Value for CapacityCode in TableB is ALL
B
6
E
As Value for CapacityCode in TableB is ALL
B
2
E
As Value for CapacityCode in TableB is ALL
I Tried Joining both the tables but the was unable to satisfy Else and ALL conditions. Hope if someone can help me on this.
There are Several **Result ** Columns like , Result 1 ,2 in both tables which needs to be updated using the same logic.
Thanks in Advance.
here is a fiddle to work on https://dbfiddle.uk/FMKdWzQT
I got the query working. by using a case statement and assigning a number so I could use max then I just remove the number.
SELECT a.other_code,
a.capacity_code,
(
SELECT SUBSTR(max(
CASE WHEN b.other_code = a.other_code AND a.capacity_code = b.capacity_code THEN concat('3',b.myresult)
WHEN b.other_code = a.other_code AND a.capacity_code is null and b.capacity_code is null THEN concat('2',b.myresult)
WHEN b.other_code = a.other_code AND b.capacity_code in ('ELSE', 'ALL') THEN concat('1',b.myresult)
else null end),2)
FROM table2 b ) as myresult
FROM table1 a
however I can not get the update to work. I tried a merge it is give me the unstable row error and I tried an update select but that is giving me single row subquery error so maybe someone else can take a look at the fiddle. here was my attempt at the update.
UPDATE table1
SET myresult = (
SELECT myresult
FROM (
SELECT a.other_code,
a.capacity_code,
(
SELECT SUBSTR(max(
CASE WHEN b.other_code = a.other_code AND a.capacity_code = b.capacity_code THEN concat('3',b.myresult)
WHEN b.other_code = a.other_code AND a.capacity_code is null and b.capacity_code is null THEN concat('2',b.myresult)
WHEN b.other_code = a.other_code AND b.capacity_code in ('ELSE', 'ALL') THEN concat('1',b.myresult)
else null end),2)
FROM table2 b ) as myresult
FROM table1 a
)t2
WHERE table1.other_code = t2.other_code and nvl(table1.capacity_code,'x') = nvl(t2.capacity_code,'x')
);

Flagging records with all missing values on right table when doing a left join

I have two tables representing client data for different years Left Table: 2019 and Right Table: 2018. Some of these clients did not exist for the prior year and my assumption is that when doing the left join, all field values from right table will be missing for those clients. Is there a way to flag these clients (or records)? Below is my query
create table joinedTable as
select a.unique_number, a.monthly_spend, b.unique_number, b.email_preference, b.client_tier,
from table2019 as a
left join table2018 as b
on a.unique_number = b.unique_number
Below is the desired output.
unique_number
monthly_spend
email_prefernce
client_tier
Flag
12AB56FG
2000
Yes
Special
0
32AB56FG
1200
Yes
Special
0
42AB56FG
2010
Yes
Special
0
56AB56HG
3000
Yes
Special
0
72AB58FG
6000
NULL
NULL
1
92AB56FG
800
NULL
NULL
1
Just use a case expression:
create table joinedTable as
select a.unique_number, a.monthly_spend, b.unique_number,
b.email_preference, b.client_tier,
(case when b.unique_number is null then 1 else 0 end) as flag
from table2019 a left join
table2018 b
on a.unique_number = b.unique_number;

T-SQL cursor or if or case when

I have this table:
Table_NAME_A:
quotid itration QStatus
--------------------------------
5329 1 Assigned
5329 2 Inreview
5329 3 sold
4329 1 sold
4329 2 sold
3214 1 assigned
3214 2 Inreview
Result output should look like this:
quotid itration QStatus
------------------------------
5329 3 sold
4329 2 sold
3214 2 Inreview
T-SQL query, so basically I want the data within "sold" status if not there then "inreview" if not there then "assigned" and also at the same time if "sold" or "inreview" or "assigned" has multiple iteration then i want the highest "iteration".
Please help me, thanks in advance :)
This is a prioritization query. One way to do this is with successive comparisons in a union all:
select a.*
from table_a a
where quote_status = 'sold'
union all
select a.*
from table_a a
where quote_status = 'Inreview' and
not exists (select 1 from table_a a2 where a2.quoteid = a.quoteid and a2.quotestatus = 'sold')
union all
select a.*
from table_a a
where quote_status = 'assigned' and
not exists (select 1
from table_a a2
where a2.quoteid = a.quoteid and a2.quotestatus in ('sold', 'Inreview')
);
For performance on a larger set of data, you would want an index on table_a(quoteid, quotestatus).
You want neither cursors nor if/then for this. Instead, you'll use a series of self-joins to get these results. I'll also use a CTE to simplify getting the max iteration at each step:
with StatusIterations As
(
SELECT quotID, MAX(itration) Iteration, QStatus
FROM table_NAME_A
GROUP BY quotID, QStats
)
select q.quotID, coalesce(sold.Iteration,rev.Iteration,asngd.Iteration) Iteration,
coalesce(sold.QStatus, rev.QStatus, asngd.QStatus) QStatus
from
--initial pass for list of quotes, to ensure every quote is included in the results
(select distinct quotID from table_NAME_A) q
--one additional pass for each possible status
left join StatusIterations sold on sold.quotID = q.quotID and sold.QStatus = 'sold'
left join StatusIterations rev on rev.quotID = q.quotID and rev.QStatus = 'Inreview'
left join StatusIterations asngd on asngd.quotID = q.quotID and asngd.QStatus = 'assigned'
If you have a table that equates a status with a numeric value, you can further improve on this:
Table: Status
QStatus Sequence
'Sold' 3
'Inreview' 2
'Assigned' 1
And the code becomes:
select t.quotID, MAX(t.itration) itration, t.QStatus
from
(
select t.quotID, MAX(s.Sequence) As Sequence
from table_NAME_A t
inner join Status s on s.QStatus = t.QStatus
group by t.quotID
) seq
inner join Status s on s.Sequence = seq.Sequence
inner join table_NAME_A t on t.quotID = seq.quotID and t.QStatus = s.QStatus
group by t.quoteID, t.QStatus
The above may look like complicated at first, but it can be faster and it will scale easily beyond three statuses without changing the code.

Oracle SQL join with counts returning null

I'm having a problem with the following query in Oracle SQL:
SELECT t.diif, t.mlf_response, v.total
FROM t_temp_rows t
LEFT OUTER JOIN
(SELECT a.diif, s.mlf_response, COUNT(a.customer_terid) total
FROM ter_details a
INNER JOIN lieu_details s ON a.lieu_id = s.lieu_id
WHERE a.customer_name = 'CUSTOMER_A' AND mlf_response IS NOT NULL
GROUP BY a.diif, s.mlf_response) v ON v.diif = t.diif AND v.mlf_response = t.mlf_response;
t_temp_rows contains all possible combinations for diif and mlf_response, regardless of whether they actually return counts in the subquery or not. I am hoping to get a count for every row in t_temp_rows, including 0 for rows with no count (I will add the NVL once it actually works).
If I run the query, rather than returning the counts in 'total' where there is a value and null elsewhere, I get null for every row.
Expected:
diif mlf_response total
---- ------------ -----
ABCD YES 12
ABCD NO 32
ABCE YES 54
ABCE NO 01
ABCF YES null
ABCF NO null
Actual:
diif mlf_response total
---- ------------ -----
ABCD YES null
ABCD NO null
ABCE YES null
ABCE NO null
ABCF YES null
ABCF NO null
What have I done wrong?
You need to add a.customer_name = 'CUSTOMER_A' to the left outer join because by adding it to the where, you are making it an inner join.
SELECT t.diif, t.mlf_response, v.total
FROM t_temp_rows t
LEFT OUTER JOIN
(SELECT a.diif, s.mlf_response, COUNT(a.customer_terid) total
FROM ter_details a ON a.customer_name = 'CUSTOMER_A'
LEFT OUTER JOIN lieu_details s ON a.lieu_id = s.lieu_id
WHERE mlf_response IS NOT NULL
GROUP BY a.diif, s.mlf_response) v ON v.diif = t.diif AND v.mlf_response = t.mlf_response;

SQL NOT exists conditional

I have three tables as described below:
dbo.ServiceEntry
ID RunLogEntry Reconciled
1 0 1
2 4 1
3 5 1
dbo.ServiceEntryPart
ID ServiceEntryID PartId ServiceEntryTypeID
1 1 3 1
2 2 4 2
3 2 4 1,2
dbo.Part
ID Desc Active (bitfield)
3 xyz 1
4 abc 1
Query as follows:
SELECT *
FROM ServiceEntry AS S
WHERE (S.RunLogEntryID is not null) AND (S.Reconciled=#ReconciledValue)
AND EXISTS (SELECT ServiceEntryID
FROM ServiceEntryPart SEP
JOIN Part on SEP.PartID = Part.ID
WHERE ((#ActivePart = 0 AND Part.Active is not null)
OR (#ActivePart = 1 and Part.Active = 0))
AND (#ServiceTypes is null
OR CHARINDEX(','+cast(SEP.ServiceTypeIDs as varchar(255))+',',','+#ServiceTypes+',') > 0))
OR (NOT EXISTS (SELECT ServiceEntryID
FROM ServiceEntryPart SEP
JOIN Part on SEP.PartID = Part.ID))
service entry has some records which contain runlogentry id of 0. If the runlogentryid value in service entry table is 0 then there will be no service entry part record for that service entry. Thats why I split them into two as you would notice from the query for example exists and not exists. the exists statement takes care of all service entries which have service entry parts and for these the filters will be applicable. If the filters have values then the not exist block will be not be needed because filters servicetypeids and activepart are for only records which have service entry parts.
So in other words if no params are passed the first exists block fetches service entries which have service parts and the not exists fetches service entries which have runlogentry id of 0 OR NOT null. This works great as it is. The problem is when the params are passed I would need to exclude the serviceentries which do not have service entry parts and when they are present I do not get the rigth results. I hope I did an okay job explaining the problem..Please help
Without trying to understand the rest of your SQL, if all you want to do is avoid the NOT EXISTS clause when your parameters are null you can do something like this.
SELECT *
FROM ServiceEntry AS S
JOIN
WHERE (S.RunLogEntryID is not null) AND (S.Reconciled=#ReconciledValue)
AND EXISTS (SELECT ServiceEntryID
FROM ServiceEntryPart SEP
JOIN Part on SEP.PartID = Part.ID
WHERE ((#ActivePart = 0 AND Part.Active is not null)
OR (#ActivePart = 1 and Part.Active = 0))
AND (#ServiceTypes is null
OR CHARINDEX(','+cast(SEP.ServiceTypeIDs as varchar(255))+',',','+#ServiceTypes+',') > 0))
OR (#ReconciledValue is null and #ActivePart is null and #ServiceTypes is null
and (NOT EXISTS (SELECT ServiceEntryID
FROM ServiceEntryPart SEP
JOIN Part on SEP.PartID = Part.ID)))
This probably isn't exactly what you want, to be honest the query seems all over the place.
You're probably looking for an active part filter like '(#ActivePart is null or #ActivePart = Part.Active)'. Your exists is implicitly taken care of by an inner join. A query that I believe is close to what you're looking for is below.
select *
FROM ServiceEntry AS S
INNER JOIN ServiceEntryPart AS SEP ON SEP.ServiceEntryID = S.ServiceEntryID
INNER JOIN Part AS P ON P.PartID = SEP.PartID
WHERE S.RunLogEntryID is not null
and S.Reconciled = #ReconciledValue
and (#ActivePart is null or #ActivePart = Part.Active)
and (#ServiceTypes is null or charindex(','+cast(SEP.ServiceTypeIDs as varchar(255))+',',','+#ServiceTypes+',') > 0
I can't be sure because I don't have the business definitions of your columns, but I suspect your conditions dealing with Part.Active are wrong. I would expect the values to be 0 or 1, not NULL or 0. So I should think the test should return TRUE when the parameter is NULL or the parameter matches the column.
Your CHARINDEX function has the parameters reversed.
You need additional parentheses to get the correct order of operation and your OR NOT EXISTS clause needs additional conditions to make it only true if the parameters are NULL.
I believe the following is much closer to what you are looking for. But I am worried about the ServiceTypes test. It will only work reliably if the parameter contains a single ServiceTypeID. If it contains multiple IDs it may not work. For example, I would think a parameter value of '1,3' should match a list of '1,2,3', but it won't.
SELECT *
FROM ServiceEntry AS S
WHERE (S.RunLogEntryID IS NOT NULL)
AND (S.Reconciled=#ReconciledValue)
AND( EXISTS(
SELECT ServiceEntryID
FROM ServiceEntryPart SEP
JOIN Part ON SEP.PartID = Part.ID
WHERE( #ActivePart IS NULL
OR #ActivePart = Part.Active
)
AND ( #ServiceTypes IS NULL
OR CHARINDEX( ','+#ServiceTypes+',',
','+cast(SEP.ServiceTypeIDs as varchar(255))+','
) > 0
)
)
OR( #ActivePart IS NULL
AND #ServiceTypes IS NULL
AND NOT EXISTS( SELECT ServiceEntryID
FROM ServiceEntryPart SEP
JOIN Part on SEP.PartID = Part.ID
)
)
)