Setting the ID in a fact table from a dimension table - sql

In my dimension table for abandoned calls I have the ID 1 Code NO , ID 2 Code YES
I am wanting to load these ID's into the fact table based on whether or not the call was abandoned using a join.
How ever the problem I'm having it that the Abandoned value in my database is NULL for NO and 1 for YES.
So when i join
INNER JOIN datamartend.dbo.Abandoned_Call_Dim
ON incoming_measure.Abandoned = Abandoned_Call_Dim.abandoned_code
It's pulling no results?
Any ideas around this?
Basically what is needed is:
I want the abandoned ID from the abandoned dimension to be 2 if the abandonded value in measure is null and abandoned id 2 if not null
Thanks

You can use a CASE WHEN clause to get around this (or ISNULL, but case when is more portable across different DB engines)
INNER JOIN datamartend.dbo.Abandoned_Call_Dim
ON case when incoming_measure.Abandoned is null then '0'
else incoming_measure.Abandoned end
= case when Abandoned_Call_Dim.abandoned_code is null then '0'
else Abandoned_Call_Dim.abandoned_code end
This will replace nulls with 0. As long as you don't have a 0 code, you should be fine. If you do, try -1, or some other value you know is not in the possible set of codes.
Another thing to do if you have an unknown set of codes would be to do the join and add:
OR (incoming_measure.Abandoned is null and Abandoned_Call_Dim.abandoned_code is null)
Which doesn't technically join - it cross joins the null records (and as long as there's only one null that matters on the abandoned call dim, you're fine).

Can you check whether it is possible for you to use Decode function for the ID before doing Join.
Decode(value) = joining column
or try using
COALESCE(REPLACE(COL, VAL_TO_B_REPLACE_IF_NOT_NULL), VALUE_TO_REPLCE_WHEN_NULL)

Related

Non null value associated with least value in other column

My data is like this:
Desired output:
I have tried using following SQL:
CASE
WHEN (MINDAY_DIFF > 0) AND (MINDAY_DIFF IS NOT NULL)
THEN FIRST_VALUE(BP_MED) OVER (PARTITION BY ID ORDER BY MINDAY_DIFF ASC)
END AS DRUG
This returns NULL.
I also tried
CASE
WHEN (MINDAY_DIFF > 0)
THEN BP_MED
ELSE NULL
END AS DRUG
It returns both non-null values of BP_MED.
I also tried NVL but that didn't work either.
Since it is in Netezza. There are fewer solutions online. Please help.
The concept here is the following working inside out:
We didn't always have analytics to make things easier: So not knowing Netezza I took a more... antiquated approach. There may be better/more efficient ways; which I would look for given a place to play around with; but I think this would work in most any RDBMS as I tried to avoid any RDBMS Specific aspects unless we're dealing with pre left join supported RDBMS.
Find the Min ID and the day difference for that ID in a result set (MinAndID)
LEFT Join back to the baseSet to get all possible values specifically to get BP_Med
Then Join back to base Table to ensure we get ALL records and then populate only the BP_Med which links to the minDay_Diff. Since it's a left join only 1 record per ID should return.
UNTESTED:
SELECT A.*, DesiredDrug.BP_MED
FROM TABLE A
LEFT JOIN (SELECT ID, Fill_Date, BP_MED, MinDay_Diff
FROM TABLE BaseSet
INNER JOIN (SELECT MIN(MINDAY_DIFF) MDD, ID
FROM TABLE
WHERE ID is not null
GROUP BY ID) MinAndID
on BaseSet.ID = MinAndID.ID
and BaseSet.MinDay_Diff = MinAndID.MDD) DesiredDrug
on A.ID = DesiredDrug
and A.Fill_Date = DesiredDrug.Fill_Date
and A.BP_Med= DesiredDrug.BP_Med
and A.MinDay_Diff = DesiredDrug.MinDay_Diff

SQL Server 2016 AdventureWorks NULL checks

I am working on 2 different assignments where I have to do null checks but I'm not sure if I have written the syntax correctly for that my instructor has not really discussed this but will be marking for it.
Below are the 2 questions and what I have written. Any help is appreciated.
Assignment 1 question: Create a list of the sales order numbers for orders not ordered online and not with a credit card. Note: 0 is false and 1 is true for bit fields. Below is the syntax i used, am i doing a null check here?
SELECT SalesOrderNumber
FROM Sales.SalesOrder_json
WHERE OnlineOrderFlag = 0 AND CreditCardID IS NULL
Assignment 2 question: list the vendors that have no products. Below is the syntax I used, am I doing a null check here?
SELECT
pv.Name AS Vendors,
COUNT(PP.ProductID) AS 'Products'
FROM
Purchasing.Vendor AS PV
LEFT JOIN
Purchasing.ProductVendor AS PPV ON PV.BusinessEntityID = PPV.BusinessEntityID
LEFT JOIN
Production.Product AS PP ON PP.ProductID = PPV.ProductID
GROUP BY
PV.Name
HAVING
COUNT(PP.ProductID) = 0;
Welcome to Stack Overflow!
In the future, please post a summary or create table statements that represents the schema of the tables used in your queries so that we have enough information to provide more than speculative responses. Even though this is the Adventure Works DB, you should start your SO journey with good habits!
please try not to post direct Assignment questions online as you will easily get done for plagiarism by most academic assignment checkers, mainly because other students may see your post, and the support that you get from the community which could result in all of you handing in the same result.
Have you run your queries? Do you think the results are correct?
If the results from your queries are correct, then the only issue is "have you done any null checks"? One could say that if your results have returned the correct results then you must have satisfied the criteria, otherwise the question wasn't formulated very well.
Null checks can be summarised into 3 patterns:
You directly compare against null using IS NULL or IS NOT NULL in your query
Use of JOIN syntax to deal with data that may have nulls.
INNER JOIN will limit the results to only records that match in both tables. Use this if you need to omit records that have a null in the foreign key field.
Non INNER joins, like LEFT JOIN. This will return results from the left table, even if there are no matching records in the joined or right table.
This is a good discussion on all supported joins: LEFT JOIN vs. LEFT OUTER JOIN in SQL Server
Use of Aggregation functions, aggregates will generally omit null values, COUNT will return 0 if all values are NULL, where as other aggregates such as SUM, MIN, MAX, AVG will return NULL if all values are NULL
Question 1
Clearly you have implemented a NULL check because you have evaluated criteria directly on the nullable column.
It looks like your answer to Question 1 is pretty good.
Question 2
While your query looks like it would return the vendors with no products, it is also returning a count of zero.
You do not need to output a column so that you can use it in a filter criteria, so remove COUNT(PP.ProductID) AS 'Products' unless you have been otherwise instructed to use it.
Is this a NULL check... That up to the interpretation, I think in this case the answer is yes. By using LEFT JOIN (or OUTER joins) you have created a result set that will have the field PP.ProductID with a value of NULL If there are no products.
Using Count in the filter criteria over that null column and recognising that a Count with a zero result means that the ProductID column was in fact null means you have evaluated a null check.
There are other ways to query for the same results, such as using NOT EXISTS. NOT EXISTS would NOT be a direct null check, because NULLABILITY was not evaluated directly.

Left Outer Join Throws NULL Value in the select statement

I am getting null values if I use a left outer join even after mentioning t.contractid=111111 in the select statement. Please let me know how to resolve this issue.
select t.contractid,r.contractid,t.batchno
from tableA t
left join tableB r
on t.contractid=r.contractid and t.PayGrp=r.PayGrp and t.PriNo=r.PriNo
where t.contractid=111111 and t.PayGrp=0 and t.batchno=201701 and t.prino=3
and r.contractid is null
Sample Output:
null null 201701
null null 201701
null null 201701
null null 201701
null null 201701
Looking at your query and making assumptions based on the query the results your are reporting would be impossible which means something improbable is going on.
Why? It is not possible for r.contractid is null and r.contractid = t.contractid and t.contractid=111111 to all to evaluate to be true. Yet your query is asking the database that question and it is returning results.
The only way to explain the result is there is a custom data type for tableA.contractid and tableB.contractid in which comparing the data types results in a null value being equal to 111111. Similarly PayGrpt.PayGrp would require a datatype which comparing a null to 0 would evaluate to true. Of course, only looking at the data definitions of the tables could tell us this.
That being said I have experience weird results with columns matching in a join statement where one side or the other was null. So before considering the other possibilities, try wrapping your join and where conditions in IsNull() this:
select t.contractid, r.contractid, t.batchno
from tableA t left join
tableB r
on IsNull(t.contractid,0) = IsNull(r.contractid,0) and
IsNull(t.PayGrp,0) = IsNull(r.PayGrp,0) and
IsNull(t.PriNo,0) = IsNull(r.PriNo, 0)
where IsNull(t.contractid,0) = 111111 and IsNull(t.PayGrp,0) = 0 and
IsNull(t.batchno,0) = 201701 and IsNull(t.prino,0) = 3 and
r.contractid is null;
Without the columns being some custom data type if the query above still produces the same result then you are dealing with some kind of system error, such as a corrupt database (or corrupt memory cache of that database) or even more unlikely a hardware error. First try rebooting the database server and the client machine performing the query (if they are not the same) and if the error still exists after a reboot try moving the data to a different database/db server and performing the same query. At that point you will know whether your have a corrupt database or are experiencing a system error on your database server.
You are restricting your query by
r.contractid is null
therefore it is ONLY returning NULL records - the result you are seeing is expected.
This is your query:
select t.contractid, r.contractid, t.batchno
from tableA t left join
tableB r
on t.contractid = r.contractid and
t.PayGrp = r.PayGrp and
t.PriNo = r.PriNo
where t.contractid = 111111 and t.PayGrp = 0 and
t.batchno = 201701 and t.prino = 3 and
r.contractid is null;
The result set will always begin with 111111, NULL, based on the WHERE clause. t.contractid has to have a value. Are you sure the table aliases are correct? That the where clause is correct?

PostgreSQL case statement for mutliple date fields

I'm presenting a query wherein I want to pull only the earliest date from a table that has two date fields. It is possible that both date fields are null. However, I only want to pull values if at least one of the fields is not null. Also, if the first date field is not null, then I want that value. In other words, I prefer the first date field.
Here is what I've come up with, but I don't feel 100% this is correct. And, I'm also thinking there's a better way to skin the proverbial cat.
Select
o.order_num,
Case
when ro.pay1_date is not null then ro.pay1_date
when ro.pay2_date is not null then ro.pay2_date
End as funding_date
From orders o
left join recon_order ro on(ro.order_id = o.order_id)
Where (ro.pay1_date is not null or ro.pay2_date is not null)
Order by funding_date desc
Limit 500
I first ran this query without the Where clause, but that just returned 500 Null values, which I never completely understood.
And as a side note I'm working with an older version of PostgreSQL 8.1 (not my choice). But just saying this because perhaps the old version won't support certain new query syntax.
Thanks in advance for any input that corrects or improves this!
You can use a least to get the least of the 2 dates. When both of them are null, it returns null. You can filter the null rows later.
SELECT *
FROM
(SELECT o.order_num,
least(ro.pay1_date,ro.pay2_date) as funding_date
FROM orders o
LEFT JOIN recon_order ro ON ro.order_id = o.order_id) x
WHERE funding_date IS NOT NULL

Access 2010 Query Confusion

Just need some quick clarification
I have 2 Queries in my Access Database that should return Inverse results:
SELECT Equipment.title
FROM Equipment
WHERE (((Equipment.[EquipmentID]) Not In (
select EquipmentID
from DownPeriod
where UpDate is null
)));
The 2nd just excludes the Not before the In.
My Confusion comes from the fact that the query posted above does not return any results if an EquipmentID field has at least 1 null value in the DownPeriod table.
It works fine if the fields are filled, and the inverse query list always works. This makes me think there's an issue with the null value.
Now this field should never be null but I wanted to know if I could still get this to work in the unlikely event a null did occur.
Thank you in advanced!
Try joins:
SELECT Equipment.title FROM Equipment INNER JOIN DownPeriod
ON Equipment.EquipmentID = DownPeriod.EquipmentID
WHERE DownPeriod.UpDate is null
and
SELECT Equipment.title FROM Equipment INNER JOIN DownPeriod
ON Equipment.EquipmentID = DownPeriod.EquipmentID
WHERE DownPeriod.UpDate is not null
See if a change in syntax fixes your issue.
Not only should this work, but I believe it is a faster practise than using the IN() NOT IN() methods (might be wrong on that, but it looks nicer to read). It also adds the ability to quickly change the "is not null" criteria just the same as IN->NOT IN
I agree with StuckAtWork's approach. However, if you still want to understand why your original approach didn't produce the results you want, I think I can help you.
There may be an issue with empty strings which could complicate the situation. But regardless of whether or not empty strings are involved you have something more fundamental to consider.
Here is my version of the Equipment table.
EquipmentID title
1 one
2 two
3 three
And here is my version of the DownPeriod table.
ID EquipmentID text_field
1 1 one
2 2 two
3 Null
4 3 three
I didn't include your UpDate field in my DownPeriod table. It's irrelevant to your problem.
I pasted your SQL into a new Access query, discarded the WHERE clause from the subquery, and got exactly the same result as this query --- no rows returned:
SELECT e.title
FROM Equipment AS e
WHERE
e.EquipmentID Not In (
SELECT EquipmentID
FROM DownPeriod
);
So consider this situation from the db engine's perspective. Using my version of the Downloads table, it has a set of values (1, 2, Null, and 3) from the subquery. You're asking it to show you the rows from Equipment where EquipmentID is NOT IN that list of values. The db engine will only give you the rows for which that condition is True.
Null is the problem. For each EquipmentID, when it considers whether that value is not present in the subquery set, it doesn't know. That Null is an unknown value ... and the unknown value might be the same as the current EquipmentID it's considering ... or might be something else. But since the db engine doesn't know the real value, it can't evaluate the condition as True, so will not include that row in the result set. The same thing happens for every row in Equipment table ... therefore your query's result set is empty (no rows).
You could get your desired results by excluding Null values from the subquery result set with a WHERE clause like the one below. But I think StuckAtWork's suggestion is a better way to go.
SELECT e.title
FROM Equipment AS e
WHERE
e.EquipmentID Not In (
SELECT EquipmentID
FROM DownPeriod
WHERE EquipmentID Is Not Null
);