0

I am using SQL Server 2014 on a Windows 10 PC. I am sending SQL queries directly into Swiftpage’s Act! CRM system (via Topline Dash). I am trying to figure out how to get the query to give me records even when some of the records have certain Null values in the Opportunity_Name field.

I am using a series of Join statements in the query to connect 4 tables: History, Contacts, Opportunity, and Groups. History is positioned at the “center” of it all. They all have many-to-many relationships with each other, and are thus each linked by an intermediate table that sits “between” the main tables, like so:

History – Group_History – Group
History – Contact_History – Contact
History – Opportunity_History – Opportunity

The intermediate tables consist only of the PKs in each of the main tables. E.g. History_Group is only a listing of HistoryIDs and GroupIDs. Thus, any given History entry can have multiple Groups, and each Group has many Histories associated with it.

Here’s what the whole SQL statement looks like:

SELECT Group_Name, Opportunity_Name, Start_Date_Time, Contact.Contact, Contact.Company, History_Type, (SQRT(SQUARE(Duration))/60) AS Hours, Regarding, HistoryID
FROM HISTORY
   JOIN Group_History
       ON Group_History.HistoryID = History.HistoryID
   JOIN "Group"
       ON Group_History.GroupID = "Group".GroupID
   JOIN Contact_History
       ON Contact_History.HistoryID = History.HistoryID
   JOIN Contact
       ON Contact_History.ContactID = Contact.ContactID
   JOIN Opportunity_History
       ON Opportunity_History.HistoryID = History.HistoryID
   JOIN Opportunity
       ON Opportunity_History.OpportunityID = Opportunity.OpportunityID
WHERE
       (  Start_Date_Time >= ('2018/02/02')       AND
          Start_Date_Time <= ('2018/02/16')                )
ORDER BY Group_NAME, START_DATE_TIME;

The problem is that when the Opportunity table is linked in, any record that has no Opportunity (i.e. a Null value) won’t show up. If you remove the Opportunity references in the Join statement, the listing will show all history events in the Date range just fine, the way I want it, whether or not they have an Opportunity associated with them.

I tried adding the following to the WHERE part of the statement, and it did not work.

  AND  (  ISNULL(Opportunity_Name, 'x') = 'x'     OR
          ISNULL(Opportunity_Name, 'x') <> 'x'              )

I also tried changing the Opportunity_Name reference up in the SELECT part of the statement to read: ISNULL(Opportunity_Name, 'x') – this didn’t work either.

Can anyone suggest a way to get the listing to contain all records regardless of whether they have a Null value in the Opportunity Name or not? Many thanks!!!

1
  • 1
    Change all the joins to left join. Commented Feb 19, 2018 at 2:42

2 Answers 2

1

I believe this is because a default JOIN statement discards unmatched rows from both tables. You can fix this by using LEFT JOIN.

Example:

CREATE TABLE dataframe (
A int,
B int
);

insert into dataframe (A,B) values 
(1, null),
(null, 1)

select a.A from dataframe a
join dataframe b ON a.A = b.A

select a.A from dataframe a
left join dataframe b ON a.A = b.A

You can see that the first query returns only 1 record, while the second returns both.

SELECT Group_Name, Opportunity_Name, Start_Date_Time, Contact.Contact, Contact.Company, History_Type, (SQRT(SQUARE(Duration))/60) AS Hours, Regarding, HistoryID
FROM HISTORY
   LEFT JOIN Group_History
       ON Group_History.HistoryID = History.HistoryID
   LEFT JOIN "Group"
       ON Group_History.GroupID = "Group".GroupID
   LEFT JOIN Contact_History
       ON Contact_History.HistoryID = History.HistoryID
   LEFT JOIN Contact
       ON Contact_History.ContactID = Contact.ContactID
   LEFT JOIN Opportunity_History
       ON Opportunity_History.HistoryID = History.HistoryID
   LEFT JOIN Opportunity
       ON Opportunity_History.OpportunityID = Opportunity.OpportunityID
WHERE
       (  Start_Date_Time >= ('2018/02/02')       AND
          Start_Date_Time <= ('2018/02/16')                )
ORDER BY Group_NAME, START_DATE_TIME;
Sign up to request clarification or add additional context in comments.

Comments

1

You will want to make sure you are using a LEFT JOIN with the table Opportunity. This will keep records that do not relate to records in the Opportunity table.

Also, BE CAREFUL you do not filter records using the WHERE clause for the Opportunity table being LEFT JOINED. Include those filter conditions relating to Opportunity instead in the LEFT JOIN ... ON clause.

2 Comments

There is no change in performance with filters in the WHERE clause as opposed to the ON clause for joined tables. It prefer the filter in the WHERE clause myself.
You may not get the same results between the two. I would be very careful here. If you put a filter on a LEFT joined table in the WHERE clause, in effect, you are turning the LEFT JOIN into an INNER JOIN. You may unexpectedly lose records.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.