Answer me with the update statement - sql-server

I have 101 records. and the prefix is a column.
[Insurance phone] is like 589-652-5256 and I have mistakenly done like
Substring ( EE.[Insurance Phone],4,3)
which result as -65 and I wanted it as 652 So I am writing update statement for same. I have different different phone number for 101 records.
When I do a select statement I got each row's middle 3 number right, but if I use update statement then 625 [1st record of 101 record] number gets updated to all 101 records.
Below are the select and update statements.
select
IC.COMPANY_NAME, EE.[Insurance Name],
substring (EE.[Insurance Phone], 5, 3) as phone
from
Insurance_Companies_28012020 EE
join
INS_COMPANIES IC on EE.[Insurance Name] = IC.COMPANY_NAME
where
ic.IS_ACTIVE = 1
and [Insurance Phone] is not null
update BUSINESS_PHONE_NUMBERS
set PREFIX = substring(EE.[Insurance Phone], 5, 3)
from Insurance_Companies_28012020 EE
join INS_COMPANIES IC on EE.[Insurance Name] = IC.COMPANY_NAME
where ic.IS_ACTIVE = 1 and [Insurance Phone] is not null

I guess your query should look like:
update t1
set t1.PREFIX = substring(EE.[Insurance Phone], 5, 3)
from BUSINESS_PHONE_NUMBERS t1
inner join Insurance_Companies_28012020 EE on ee.KEY_COLUMN = t1.KEY_COLUMN -- here you should link these two tables
inner join INS_COMPANIES IC on EE.[Insurance Name] = IC.COMPANY_NAME
where ic.IS_ACTIVE = 1
and [Insurance Phone] is not null
Edited:
Your update statement doesn't link tables BUSINESS_PHONE_NUMBERS and Insurance_Companies_28012020, which produces a Cartesian product in the execution plan, which leads to the strange behaviour of the end update result. You get the situation: you need to update N rows, but you have N*M rows with all possible combinations. It's hard to say which one of them will be selected to update. In your case, it is the first record from Insurance_Companies_28012020 table.
Also, in your UPDATE statement you can add the condition to WHERE clause: BUSINESS_PHONE_NUMBERS.KEY_COLUMN = EE.KEY_COLUMN. This should give the same result as in my UPDATE.

3o...,
Thanks for your answer it helped me to get to the exact destination.
As I said there is no relation between ee and t1. So I need to change your update statement as below. And it worked fine for me.
update t1
set t1.PREFIX = substring(EE.[Insurance Phone], 5, 3)
from BUSINESS_PHONE_NUMBERS t1
inner join INS_COMPANIES IC on IC.INS_COMPANY_ID = t1.OWNER_ID -- here you should link these two tables
inner join Insurance_Companies_28012020 EE on EE.[Insurance Name] = IC.COMPANY_NAME
where ic.IS_ACTIVE = 1
and [Insurance Phone] is not null

Related

Insert using Insert Into and Inner Join

I'm inserting rows of data from one table's column to another table's column. This is my work done:
Insert into [Inventory](Cost)
Select cast(a.[CCost] as numeric(18,6)) from [InventoryTemp] as a
Inner join [Inventory] as b on a.[ID] = b.[ID]
I have 10000 rows of data in my [Inventory] table (ID column is filled up) but when the above query was executed, the Cost data started from 10001 until 20000.
Inventory InventoryTemp
ID Cost ID Cost
1 1 3.12
3 3 9.90
18 18 8.80
The result I want
Inventory
ID Cost
1 3.12
3 9.90
18 8.80
If I have read your question correctly, I think you are trying to update the values of the cost column in your Inventory table, based on the values in the InventoryTemp table.
Therefore you want to perform an UPDATE command rather than an INSERT.
An example of this would be:
UPDATE
Inventory
SET
Inventory.Cost = InventoryTemp.Cost
FROM
Inventory
INNER JOIN
InventoryTemp
ON
Inventory.ID = InventoryTemp.ID
For more info please see this question: How do I UPDATE from a SELECT in SQL Server?
You need to use UPDATE instead of `INSERT'
UPDATE i
SET [Cost] = it.[Cost]
FROM [Inventory] i
INNER JOIN [InventoryTemp] it
ON i.ID = it.ID
Try use update.
UPDATE b
SET b.Cost = a.Cost
FROM
[InventoryTemp] as a
Inner join [Inventory] as b on a.[ID] = b.[ID]

Update records SQL?

First when I started this project seemed very simple. Two tables, field tbl1_USERMASTERID in Table 1 should be update from field tbl2_USERMASTERID Table 2. After I looked deeply in Table 2, there is no unique ID that I can use as a key to join these two tables. Only way to match the records from Table 1 and Table 2 is based on FIRST_NAME, LAST_NAME AND DOB. So I have to find records in Table 1 where:
tbl1_FIRST_NAME equals tbl2_FIRST_NAME
AND
tbl1_LAST_NAME equals tbl2_LAST_NAME
AND
tbl1_DOB equals tbl2_DOB
and then update USERMASTERID field. I was afraid that this can cause some duplicates and some users will end up with USERMASTERID that does not belong to them. So if I find more than one record based on first,last name and dob those records would not be updated. I would like just to skip and leave them blank. That way I wouldn't populate invalid USERMASTERID. I'm not sure what is the best way to approach this problem, should I use SQL or ColdFusion (my server side language)? Also how to detect more than one matching record?
Here is what I have so far:
UPDATE Table1 AS tbl1
LEFT OUTER JOIN Table2 AS tbl2
ON tbl1.dob = tbl2.dob
AND tbl1.fname = tbl2.fname
AND tbl1.lname = tbl2.lname
SET tbl1.usermasterid = tbl2.usermasterid
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = ''
Here is query where I tried to detect duplicates:
SELECT DISTINCT
tbl1.FName,
tbl1.LName,
tbl1.dob,
COUNT(*) AS count
FROM Table1 AS tbl1
LEFT OUTER JOIN Table2 AS tbl2
ON tbl1.dob = tbl2.dob
AND tbl1.FName = tbl2.first
AND tbl1.LName = tbl2.last
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = ''
AND LTRIM(RTRIM(tbl1.first)) <> ''
AND LTRIM(RTRIM(tbl1.last)) <> ''
AND LTRIM(RTRIM(tbl1.dob)) <> ''
GROUP BY tbl1.FName,tbl1.LName,tbl1.dob
Some data after I tested query above:
First Last DOB Count
John Cook 2008-07-11 2
Kate Witt 2013-06-05 1
Deb Ruis 2016-01-22 1
Mike Bennet 2007-01-15 1
Kristy Cruz 1997-10-20 1
Colin Jones 2011-10-13 1
Kevin Smith 2010-02-24 1
Corey Bruce 2008-04-11 1
Shawn Maiers 2016-08-28 1
Alenn Fitchner 1998-05-17 1
If anyone have idea how I can prevent/skip updating duplicate records or how to improve this query please let me know. Thank you.
You could check for and avoid duplicate matches using with common_table_expression (Transact-SQL)
along with row_number()., like so:
with cte as (
select
t.fname
, t.lname
, t.dob
, t.usermasterid
, NewUserMasterId = t2.usermasterid
, rn = row_number() over (partition by t.fname, t.lname, t.dob order by t2.usermasterid)
from table1 as t
inner join table2 as t2 on t.dob = t2.dob
and t.fname = t2.fname
and t.lname = t2.lname
and ltrim(rtrim(t.usermasterid)) = ''
)
--/* confirm these are the rows you want updated
select *
from cte as t
where t.NewUserMasterId != ''
and not exists (
select 1
from cte as i
where t.dob = i.dob
and t.fname = i.fname
and t.lname = i.lname
and i.rn>1
);
--*/
/* update those where only 1 usermasterid matches this record
update t
set t.usermasterid = t.NewUserMasterId
from cte as t
where t.NewUserMasterId != ''
and not exists (
select 1
from cte as i
where t.dob = i.dob
and t.fname = i.fname
and t.lname = i.lname
and i.rn>1
);
--*/
I use the cte to extract out the sub query for readability. Per the documentation, a common table expression (cte):
Specifies a temporary named result set, known as a common table expression (CTE). This is derived from a simple query and defined within the execution scope of a single SELECT, INSERT, UPDATE, or DELETE statement.
Using row_number() to assign a number for each row, starting at 1 for each partition of t.fname, t.lname, t.dob. Having those numbered allows us to check for the existence of duplicates with the not exists() clause with ... and i.rn>1
You could use a CTE to filter out the duplicates from Table1 before joining:
; with CTE as (select *
, count(ID) over (partition by LastName, FirstName, DoB) as IDs
from Table1)
update a
set a.ID = b.ID
from Table2 a
left join CTE b
on a.FirstName = b.FirstName
and a.LastName = b.LastName
and a.Dob = b.Dob
and b.IDs = 1
This will work provided there are no exact duplicates (same demographics and same ID) in table 1. If there are exact duplicates, they will also be excluded from the join, but you can filter them out before the CTE to avoid this.
Please try below SQL:
UPDATE Table1 AS tbl1
INNER JOIN Table2 AS tbl2
ON tbl1.dob = tbl2.dob
AND tbl1.fname = tbl2.fname
AND tbl1.lname = tbl2.lname
LEFT JOIN Table2 AS tbl3
ON tbl3.dob = tbl2.dob
AND tbl3.fname = tbl2.fname
AND tbl3.lname = tbl2.lname
AND tbl3.usermasterid <> tbl2.usermasterid
SET tbl1.usermasterid = tbl2.usermasterid
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = ''
AND tbl3.usermasterid is null

Create and execute stored procedure in SQL Server

I have four tables:
dbo.Projects (id, ProjectName, Areas, PaymentSystem, Districts.id, purpose.id, types.id, etc)
dbo.Districts(id, DistrictsName)
dbo.Purpose (id, PurposeName) - has residential & commercial
dbo.Types (id, typName)
I want to select DistrictsName where PurposeName = 'residential'
I tried this procedure :
CREATE PROCEDURE [dbo].[SearchResidentialProjects]
AS
SELECT
dbo.Projects.ID,
dbo.Districts.DistrictName,
dbo.Purpose.PurposeName
FROM
dbo.Projects
INNER JOIN
dbo.Purpose ON dbo.Projects.PurposeID = dbo.Purpose.ID
INNER JOIN
dbo.Districts ON dbo.Projects.DistrictID = dbo.Districts.ID
WHERE
dbo.Purpose.PurposeName = N'Residential'
this is the result from this procedure:
ID DistrictsName PurposeName
1 District1 residential
2 District1 residential
3 District2 residential
4 District2 residential
i want display the DistrictsName without duplicate or with different values , i a have also one more project per district in projects records . this what i want to display :
ID DistrictsName PurposeName
1 District1 residential
2 District2 residential
how i get this result ,
any help is appreciated.
Why do people use stored procedures when views are much more appropriate? I have never understood this. It seems peculiar to SQL Server users.
In any case, you can do what you want with aggregation:
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as id,
d.DistrictName, p.PurposeName
FROM dbo.Projects pr INNER JOIN
dbo.Purpose pu
ON pr.PurposeID = pu.ID INNER JOIN
dbo.Districts d
ON pr.DistrictID = d.ID
WHERE pu.PurposeName = N'Residential'
GROUP BY d.DistrictName, p.PurposeName;
The use of table aliases makes the query much easier to write and to read.
In addition, I don't understand the id column being output. Why would you want to construct a new id? In any case, that is what your data suggests.
Use DISTINCT statement for removing the duplicates:
CREATE PROCEDURE [dbo].[SearchResidentialProjects]
AS
SELECT DISTINCT
dbo.Projects.ID,
dbo.Districts.DistrictName,
dbo.Purpose.PurposeName
FROM
dbo.Projects
INNER JOIN
dbo.Purpose ON dbo.Projects.PurposeID = dbo.Purpose.ID
INNER JOIN
dbo.Districts ON dbo.Projects.DistrictID = dbo.Districts.ID
WHERE
dbo.Purpose.PurposeName = N'Residential'

Joining two queries horizontally

I wrote two queries below that produce one row of data each.
What is the best way to combine them such that I am LEFT with only a single row of data?
These are coming FROM two DISTINCT databases named : [ASN01] and [dsi_ASN_dsicx]
I have 70 pairs of databases like this but am showing only one for simplicity.
The fact that the three letter acronym ASN is common to both database names is no mistake and if needed can be a part of the solution.
Current Results:
Site, Elligence (header)
ASN, 100.00
Site, GP_Total (header)
ASN, 120.00
Desired results:
Site, GP_Total, Elligence (header)
ASN, 120.00, 100.00
SELECT 'ASN' AS Site ,
CASE SUM(perdblnc)
WHEN NULL THEN 0
ELSE -1 * SUM(PERDBLNC)
END AS GP_Total
FROM [ASN01].[dbo].[GL10110] T1
LEFT OUTER JOIN [ASN01].[dbo].[GL00105] T2 ON [T1].[ACTINDX] = [T2].[ACTINDX]
WHERE YEAR1 = 2012
AND PERIODID IN ( '2' )
AND ACTNUMST IN ( '4200-0000-C', '6940-0000-C', '6945-0000-C',
'6950-0000-C' )
SELECT 'ASN' AS [Site] ,
SUM(pi.amount) AS [Elligence]
FROM [dsi_ASN_dsicx].dbo.charge c
LEFT JOIN [dsi_ASN_dsicx].dbo.paymentitem pi ON c.idcharge = pi.chargeid
LEFT JOIN [dsi_ASN_dsicx].dbo.payment p ON pi.paymentid = p.idpayment
LEFT JOIN [dsi_ASN_dsicx].dbo.paymenttype pt ON p.paymenttypeid = pt.idpaymenttype
WHERE pi.amount != 0
AND pt.paymentmethod NOT IN ( '5', '7' )
AND pt.paymentmethod IS NOT NULL
AND p.sdate >= '20120201'
AND p.sdate <= '20120229'
WIthout going through and changing any of your queries, the easiest way would be to use temp tables using the "WITH" common_table_expression. Table1 and Table2 are temp tables created from your select statements. Therefore, we select table1 and join table2.
Let me know if there are any syntax problems, I don't have anything to test this on presently.
;With Table1 as (SELECT 'ASN' as Site, Case sum(perdblnc)
WHEN NULL THEN 0
ELSE -1*sum(PERDBLNC) END as GP_Total
FROM [ASN01].[dbo].[GL10110] T1
Left Outer Join [ASN01].[dbo].[GL00105] T2
ON [T1]. [ACTINDX]= [T2]. [ACTINDX]
WHERE YEAR1 = 2012
AND PERIODID in ('2')
AND ACTNUMST in ('4200-0000-C', '6940-0000-C', '6945-0000-C', '6950-0000-C'))
, Table2 as (SELECT
'ASN' as [Site],
SUM(pi.amount) as [Elligence]
FROM [dsi_ASN_dsicx].dbo.charge c
LEFT JOIN [dsi_ASN_dsicx].dbo.paymentitem pi on c.idcharge = pi.chargeid
LEFT JOIN [dsi_ASN_dsicx].dbo.payment p on pi.paymentid = p.idpayment
LEFT JOIN [dsi_ASN_dsicx].dbo.paymenttype pt on p.paymenttypeid = pt.idpaymenttype
WHERE pi.amount != 0
AND pt.paymentmethod not in ('5','7')
AND pt.paymentmethod is not null
AND p.sdate >='20120201' and p.sdate <= '20120229')
SELECT * FROM Table1
LEFT JOIN Table2 ON Table1.site = Table2.site
Hope this helps! Marks as answer if it is =)

SQL getting multiple columns into one column

I have this query that I am using to create a report:
SELECT DISTINCT
Appointment.ActivityId, Appointment.ScheduledStart, Appointment.OwnerIdName, Contact.AccountIdName, Appointment.new_ContactPersonName,
Appointment.Subject, Appointment.new_ColderNotes, Account.AccountId, Contact_1.ContactId, SystemUser.SystemUserId, SystemUser.FullName AS OptionalOwner,
Contact_1.FullName AS OptionalContact, Account.Name AS OptionalAccount, ActivityParty.PartyId, ActivityParty.ParticipationTypeMask,
Contact_1.FullName AS RequiredContact, Account.Name AS RequiredAccount, SystemUser.FullName AS RequiredOwner, Account.new_BusinessUnit
FROM
Contact AS Contact_1 RIGHT OUTER JOIN
Account RIGHT OUTER JOIN
SystemUser RIGHT OUTER JOIN
Appointment INNER JOIN
ActivityParty ON Appointment.ActivityId = ActivityParty.ActivityId ON SystemUser.SystemUserId = ActivityParty.PartyId ON Account.AccountId = ActivityParty.PartyId ON
Contact_1.ContactId = ActivityParty.PartyId LEFT OUTER JOIN
Contact ON Appointment.new_ContactPerson = Contact.ContactId
This returns rows for each type of User. So one row for Required user and one row for Optional User etc.
This is a small sample of data:
ActivityId ScheduledStart OwnerIdName AccountIdName new_ContactPersonName Subject new_ColderNotes AccountId ContactId SystemUserId OptionalOwner OptionalContact OptionalAccount PartyId ParticipationTypeMask RequiredContact RequiredAccount RequiredOwner new_BusinessUnit
f9ca2637-580a-e111-b263-001ec928e97f 11/17/2011 3:00:00 PM Bob Schulze Surmodics Pharmaceuticals Jason Kennedy Sales Visit - Surmodics NULL NULL NULL f69530fc-da00-e111-b263-001ec928e97f Bob Schulze NULL NULL f69530fc-da00-e111-b263-001ec928e97f 7 NULL NULL Bob Schulze NULL
f9ca2637-580a-e111-b263-001ec928e97f 11/17/2011 3:00:00 PM Bob Schulze Surmodics Pharmaceuticals Jason Kennedy Sales Visit - Surmodics NULL NULL NULL f69530fc-da00-e111-b263-001ec928e97f Bob Schulze NULL NULL f69530fc-da00-e111-b263-001ec928e97f 9 NULL NULL Bob Schulze NULL
f9ca2637-580a-e111-b263-001ec928e97f 11/17/2011 3:00:00 PM Bob Schulze Surmodics Pharmaceuticals Jason Kennedy Sales Visit - Surmodics NULL c629fb14-1101-e111-b263-001ec928e97f NULL NULL NULL NULL Surmodics Pharmaceuticals c629fb14-1101-e111-b263-001ec928e97f 5 NULL Surmodics Pharmaceuticals NULL NULL
f9ca2637-580a-e111-b263-001ec928e97f 11/17/2011 3:00:00 PM Bob Schulze Surmodics Pharmaceuticals Jason Kennedy Sales Visit - Surmodics NULL c629fb14-1101-e111-b263-001ec928e97f NULL NULL NULL NULL Surmodics Pharmaceuticals c629fb14-1101-e111-b263-001ec928e97f 8 NULL Surmodics Pharmaceuticals NULL NULL
As you can see they are the same ActivityID but have different ParticipationTypeMasks those are the 5, 7 , 9.
Using all this when I create a report I get something like this:
It creates a row for each ParticipationMask. What I am trying to do is making it so if the ParticipationMask is 1, 2, or 3 those names go into the Sales column and if it is 4, 5, 6 it goes in the Other Column and only have one row per activity, not one per ParticipationMask. Anyway to do this? I'm stuck. I'm open to doing it in SQL or SSRS.
Thanks!
This is a shot in the dark because we don't really know your data, but if you like your existing query it may be possible to simply use it twice but with a where clause like so:
SELECT
-- Common stuff?
ISNULL(Sales.ActivityId, Other.ActivityId), ISNULL(Sales.ScheduledStart, Other.ScheduledStart), ISNULL(Sales.OwnerIdName, Other.OwnerIdName), ISNULL(Sales.AccountIdName, Other.AccountIdName), ISNULL(Sales.new_ContactPersonName, Other.new_ContactPersonName), ISNULL(Sales.[Subject], Other.[Subject]), ISNULL(Sales.new_ColderNotes, Other.new_ColderNotes)
-- Sales stuff?
, Sales.AccountId, Sales.ContactId, Sales.SystemUserId, Sales.OptionalOwner, Sales.OptionalContact, Sales.OptionalAccount, Sales.PartyId, Sales.ParticipationTypeMask, Sales.RequiredContact, Sales.RequiredAccount, Sales.RequiredOwner, Sales.new_BusinessUnit
-- Other Stuff?
, Other.AccountId, Other.ContactId, Other.SystemUserId, Other.OptionalOwner, Other.OptionalContact, Other.OptionalAccount, Other.PartyId, Other.ParticipationTypeMask, Other.RequiredContact, Other.RequiredAccount, Other.RequiredOwner, Other.new_BusinessUnit
FROM
(
SELECT DISTINCT
Appointment.ActivityId, Appointment.ScheduledStart, Appointment.OwnerIdName, Contact.AccountIdName, Appointment.new_ContactPersonName,
Appointment.Subject, Appointment.new_ColderNotes, Account.AccountId, Contact_1.ContactId, SystemUser.SystemUserId, SystemUser.FullName AS OptionalOwner,
Contact_1.FullName AS OptionalContact, Account.Name AS OptionalAccount, ActivityParty.PartyId, ActivityParty.ParticipationTypeMask,
Contact_1.FullName AS RequiredContact, Account.Name AS RequiredAccount, SystemUser.FullName AS RequiredOwner, Account.new_BusinessUnit
FROM
Contact AS Contact_1 RIGHT OUTER JOIN
Account RIGHT OUTER JOIN
SystemUser RIGHT OUTER JOIN
Appointment INNER JOIN
ActivityParty ON Appointment.ActivityId = ActivityParty.ActivityId ON SystemUser.SystemUserId = ActivityParty.PartyId ON Account.AccountId = ActivityParty.PartyId ON
Contact_1.ContactId = ActivityParty.PartyId LEFT OUTER JOIN
Contact ON Appointment.new_ContactPerson = Contact.ContactId
-- Limit this part to Sales?
WHERE ParticipationTypeMask BETWEEN 1 AND 3
) as Sales
FULL OUTER JOIN
(
SELECT DISTINCT
Appointment.ActivityId, Appointment.ScheduledStart, Appointment.OwnerIdName, Contact.AccountIdName, Appointment.new_ContactPersonName,
Appointment.Subject, Appointment.new_ColderNotes, Account.AccountId, Contact_1.ContactId, SystemUser.SystemUserId, SystemUser.FullName AS OptionalOwner,
Contact_1.FullName AS OptionalContact, Account.Name AS OptionalAccount, ActivityParty.PartyId, ActivityParty.ParticipationTypeMask,
Contact_1.FullName AS RequiredContact, Account.Name AS RequiredAccount, SystemUser.FullName AS RequiredOwner, Account.new_BusinessUnit
FROM
Contact AS Contact_1 RIGHT OUTER JOIN
Account RIGHT OUTER JOIN
SystemUser RIGHT OUTER JOIN
Appointment INNER JOIN
ActivityParty ON Appointment.ActivityId = ActivityParty.ActivityId ON SystemUser.SystemUserId = ActivityParty.PartyId ON Account.AccountId = ActivityParty.PartyId ON
Contact_1.ContactId = ActivityParty.PartyId LEFT OUTER JOIN
Contact ON Appointment.new_ContactPerson = Contact.ContactId
-- Limit this part to Other?
WHERE ParticipationTypeMask BETWEEN 4 AND 6
) AS Other ON Sales.ActivityId = Other.ActivityId -- More cols for join?
One way is to join to your table twice and add the ParticipationMask filters to the Join Clause. e.g
JOIN activityparty activityparty_sales
ON appointment.activityid = activityparty_sales.activityid
AND activityparty_sales.participationtypemask IN ( 1, 2, 3 )
And
JOIN activityparty activityparty_other
ON appointment.activityid = activityparty_other.activityid
AND activityparty_other.participationtypemask IN ( 4, 5, 6 )
This is somewhat complicated (for me at least) because you've got a bunch of Right joins with nested joins.
I converted them into more standard joins (but without an ability to test I could be wrong)
SELECT [your fields]
FROM appointment
INNER JOIN activityparty activityparty_sales
ON appointment.activityid = activityparty_sales.activityid
AND activityparty_sales.participationtypemask IN ( 1, 2, 3 )
LEFT JOIN systemuser systemuser_sales
ON systemuser_sales.systemuserid = activityparty_sales.partyid
LEFT JOIN ACCOUNT account_sales
ON account_sales.accountid = activityparty_sales.partyid
LEFT JOIN contact AS contact_1_sales
ON contact_1_sales.contactid = activityparty_sales.partyid
LEFT OUTER JOIN contact contact_sales
ON appointment.new_contactperson = contact_sales.contactid
INNER JOIN activityparty activityparty_other
ON appointment.activityid = activityparty_other.activityid
AND activityparty_other.participationtypemask IN ( 4, 5, 6 )
LEFT JOIN systemuser systemuser_other
ON systemuser_other.systemuserid = activityparty_other.partyid
LEFT JOIN ACCOUNT account_other
ON account_other.accountid = activityparty_other.partyid
LEFT JOIN contact AS contact_1_other
ON contact_1_other.contactid = activityparty_other.partyid
LEFT OUTER JOIN contact contact_other
ON appointment.new_contactperson = contact_other.contactid
Another thing that complicates this is that without knowing your data may have multiple values for Sales and Other
If that's the case then you'll need to add two CTEs that use Row_Number and then Add a where clause
WHERE
(CTE_sales.activityid is null
or CTE_other.activityid is null
or CTE_sales.RN = CTE_other.RN)
*Actually a CTE isn't a bad idea
If I am interpreting your question correctly it sounds like you need to use sub queries.
Write one sub query to find the “Sales” data for the activity and another to find your “Other” data for the activity. You can then join each one back to the base activity record. Note that depending on exactly how your data is structured the sub queries could be as simple as adding an AND clause to the join which filters it down to just the desired record types, and then repeating the join with different criteria.
This should work assuming there is only one of each record type for the activity, if you start running into situations where a sub query can return more than one row per activity then you may have problems with it breeding extra rows while it tries to match up all of the possible combinations.

Resources