Removing these darn NULLS - sql

I have an issue that would seem straight forward but for some reason I cannot get rid of my null values from the blow select. All I need this to do is return one row, that one without the NULL value. Can someone please point out the error in my ways? :)
The result that I get when running:
EffectiveDate Refund
2015-05-18 00:00:00.000 NULL
2015-05-18 00:00:00.000 1
What I expect back:
EffectiveDate Refund
2015-05-18 00:00:00.000 1
My query:
select md.EffectiveDate,
CASE
WHEN
ISNULL(ConfigID,'') = 3 THEN '1'
WHEN
ISNULL(ConfigID,'') = 4 THEN '2'
END AS Refund
from dbo.PartnerBankConfig md
where md.PartnerID= 100000509
and md.EffectiveDate = (select max(EffectiveDate)
from dbo.PartnerBankConfig
where PartnerID = 100000509
and ISNULL(ConfigID,'') IS NOT NULL)

You get this null because the data doesn't match any condition in your case statement. In other words, in that row you have a value for ConfigID that is neither 3 nor 4. The behavior of a case statement when none of the conditions match is to evaluate to null, and thus null is being returned for this row.
In addition, this function: ISNULL(ConfigID,'') replaces any null with an empty string (a non-null value).
Therefore, ISNULL(ConfigID,'') IS NOT NULL doesn't make sense. It is always going to be true, because ISNULL is always returning a non-null value. You should remove every use of ISNULL() from your query, as none of them are necessary.

As Dan explains, your use of ISNULL() is just not appropriate. From your description, you seem to want this simpler query:
select md.EffectiveDate,
(CASE WHEN ConfigID = 3 THEN 1
WHEN ConfigID = 4 THEN 2
END) as Refund
from (select md.*, max(EffectiveDate) over (partition by PartnerId) as maxed
from dbo.PartnerBankConfig md
where md.PartnerID = 100000509 and
configId in (3, 4)
) md
where md.EffectiveDate = maxed;
Or, even more simply:
select top (1) with ties md.EffectiveDate,
(CASE WHEN ConfigID = 3 THEN 1
WHEN ConfigID = 4 THEN 2
END) as Refund
from (select md.*, max(EffectiveDate) over (partition by PartnerId) as maxed
from dbo.PartnerBankConfig md
where md.PartnerID = 100000509 and
ConfigId in (3, 4)
order by EffectiveDate desc;

Related

Last record per transaction

I am trying to select the last record per sales order.
My query is simple in SQL Server management.
SELECT *
FROM DOCSTATUS
The problem is that this database has tens of thousands of records, as it tracks all SO steps.
ID SO SL Status Reason Attach Name Name Systemdate
22 951581 3 Processed Customer NULL NULL BW 2016-12-05 13:33:27.857
23 951581 3 Submitted Customer NULL NULL BW 2016-17-05 13:33:27.997
24 947318 1 Hold Customer NULL NULL bw 2016-12-05 13:54:27.173
25 947318 1 Invoices Submit Customer NULL NULL bw 2016-13-05 13:54:27.300
26 947318 1 Ship Customer NULL NULL bw 2016-14-05 13:54:27.440
I would to see the most recent record per the SO
ID SO SL Status Reason Attach Name Name Systemdate
23 951581 4 Submitted Customer NULL NULL BW 2016-17-05 13:33:27.997
26 947318 1 Ship Customer NULL NULL bw 2016-14-05 13:54:27.440
Well I'm not sure how that table has two Name columns, but one easy way to do this is with ROW_NUMBER():
;WITH cte AS
(
SELECT *,
rn = ROW_NUMBER() OVER (PARTITION BY SO ORDER BY Systemdate DESC)
FROM dbo.DOCSTATUS
)
SELECT ID, SO, SL, Status, Reason, ..., Systemdate
FROM cte WHERE rn = 1;
Also please always reference the schema, even if today everything is under dbo.
I think you can keep it this simple:
SELECT *
FROM DOCSTATUS
WHERE ID IN (SELECT MAX(ID)
FROM DOCSTATUS
GROUP BY SO)
You want only the maximum ID from each SO.
An efficient method with the right index is a correlated subquery:
select t.*
from t
where t.systemdate = (select max(t2.systemdate) from t t2 where t2.so = t.so);
The index is on (so, systemdate).

SQL conditional join with subselect

I do not understand why this code isn't working. I have a join which needs a different join condition depending on the result of a subselect.
When the term date is null, I want this to come after the and operator: and vs.term_date is null
When the term date is not null, I want the subquery below to come after the and operator. I need to join on the max effective date: vs.eff_date = (subquery)
I realize this code is messy, but I have to aggregate with a subselect since there are multiple rows coming back and I only want one. (but open to other solutions)
select *
From loc
inner join VendorSite vs
on loc.Record_Number = vs.SITE_NO
and --conditional join
case
when
(
case
when --if term date is null i want this after "and"
(select top 1 TERM_DATE
from VendorSite vs2
where vs2.SITE_NO = vs.SITE_NO
order by TERM_DATE asc) is null
then 1
else 0
end
) = 1
then vs.term_date is null
else --when term_date isn't null use max eff date
vs.eff_date =
(select max(eff_date)
from VendorSite vs2
where vs2.SITE_NO = loc.Record_Number)
end
Example: From the below dataset, I would only want to see the row where term_date is null come back.
site_no eff_date term_date
13588 2007-01-01 00:00:00.000 NULL
13588 2007-03-01 00:00:00.000 2007-11-09 00:00:00.000

ORDER BY ASC with NULL last and subsequent ordering not working

I have a query that has 3 ORDER BY columns: the second ORDER BY has to have NULL values ordered last; the third ORDER BY doesn't seem to work.
The first table below is what my query produces - it orders the NULL last as desired, but the tertiary order isn't correct (row 3 and 4 are inverted).
Status OK on row 3 should be after Status LATE on row 4 since LATE is ordinal before OK.
SELECT * FROM t
ORDER BY ORG, IIF(Earliest_Date IS NULL, 1, 0), Status;
ORG Earliest_Date Status
A 1/1/2019 LATE
A 2/2/2019 OK
A NULL OK
A NULL LATE
B 3/1/2019 LATE
B NULL OK
This is the desired outcome with NULLs ordered last and tertiary order ascending with LATE before OK:
Desired:
ORG Earliest_Date Status
A 1/1/2019 LATE
A 2/2/2019 OK
A NULL LATE
A NULL OK
B 3/1/2019 LATE
B NULL OK
Any help is greatly appreciated.
I don't have Access so I can't test this out myself but it sounds like all you need to do is to specify ASC after your tertiary ORDER BY criteria like this:
SELECT *
FROM t
ORDER BY ORG, IIF(Earliest_Date IS NULL, 1, 0), Status ASC;
The code should be fine, probably other problem, tried the code below to test it first:
SELECT * FROM t
ORDER BY ORG, Status, IIF(Earliest_Date IS NULL, 1, 0)

SQL Query - Sum Rows

I am attempting to calculate a value inside a view, from 2 rows on a table.
SQL Server.
The table has these columns
----------------------------------------------
|RefId | Quantity | TransferFrom | TransferTo |
----------------------------------------------
|5601 | 100 | 5580 | null |
-----------------------------------------------
|5850 | 200 | null | 5601 |
-----------------------------------------------
I would like to add the quantity of the current row, and the quantity of another row if the other row's TransferTo col equals the current row's RefId.
In the view I have:
MyAmount = [Quantity] + (SELECT [Quantity]
FROM MyTable
WHERE [TransferTo] = [RefId])
However, this is returning NULL.
Would I better be using variables or a CAST function?
Thanks in advance for any input
The problem is that the subquery could be returning NULL. This is a case where ISNUL() is preferable over COALESCE():
MyAmount = ([Quantity] +
ISNULL((SELECT t2.[Quantity] FROM MyTable t2 WHERE t2.[TransferTo] = t.[RefId]), 0)
)
(This assumes that the table alias from the outer query is t.)
ISNULL() is preferable because COALESCE() might evaluate the subquery twice, which is unnecessary overhead. (Otherwise, I prefer COALESCE() because it is the ANSI standard function.)
Note: If you are using correlated subqueries, you should always qualify all your column names.
You Will Get the Value as NULL while adding 2 values if either of the value is NULL. So Use the ISNULL() on both sides to avoid the NULL.
MyAmount = ISNULL([Quantity],0.00) + ISNULL((SELECT [Quantity]
FROM MyTable
WHERE [TransferTo] = [RefId]),0.00)
Do you want get this result?
;WITH MyTable(RefId,Quantity,TransferFrom,TransferTo) AS(
SELECT 5601,100,5580,null UNION ALL
SELECT 5850 ,200,null , 5601
)
SELECT x.*,MyAmount = x.[Quantity]+ISNULL( y.[Quantity] ,0)
FROM MyTable x
LEFT JOIN MyTable AS y ON x.TransferTo=y.RefId
RefId Quantity TransferFrom TransferTo MyAmount
5601 100 5580 NULL 100
5850 200 NULL 5601 300

Count of group for null is always 0 (zero)

In TSql what is the recommended approach for grouping data containing nulls?
Example of the type of query:
Select Group, Count([Group])
From [Data]
Group by [Group]
It appears that the count(*) and count(Group) both result in the null group displaying 0.
Example of the expected table data:
Id, Group
---------
1 , Alpha
2 , Null
3 , Beta
4 , Null
Example of the expected result:
Group, Count
---------
Alpha, 1
Beta, 1
Null, 0
This is the desired result which can be obtained by count(Id). Is this the best way to get this result and why does count(*) and count(Group) return an "incorrect" result?
Group, Count
---------
Alpha, 1
Beta, 1
Null, 2
edit: I don't remember why I thought count(*) did this, it may be the answer I'm looking for..
The best approach is to use count(*) which behaves exactly like count(1) or any other constant.
The * will ensure every row is counted.
Select Group, Count(*)
From [Data]
Group by [Group]
The reason null shows 0 instead of 2 in this case is because each cell is counted as either 1 or null and null + null = null so the total of that group would also be null. However the column type is an integer so it shows up as 0.
Just do
SELECT [group], count([group])
GROUP BY [group]
SQL Fiddle Demo
Count(id) doesn't gives the expected result as mentioned in question. Gives value of 2 for group NULL
try this..
Select Group, Count(isNull(Group,0))
From [Data]
Group by [Group]
COUNT(*) should work:
SELECT Grp,COUNT(*)
FROM tab
GROUP BY Grp
One more solution could be following:
SELECT Grp, COUNT(COALESCE(Grp, ' '))
FROM tab
GROUP BY Grp
Here is code at SQL Fiddle