SELECT count(AccountNumber),
CustomerType = CASE WHEN personid IS NOT NULL AND StoreID IS NOT NULL
THEN 'Store with contact'
when personid IS NOT NULL AND StoreID IS NULL
THEN 'store'
when personid IS NULL AND StoreID IS NOT NULL
THEN 'Person'
ELSE 'Error'
end
FROM Sales.Customer AS c
LEFT JOIN Person.Person AS P
ON c.PersonID = p.BusinessEntityID
LEFT JOIN Sales.Store ON
c.StoreID = Store.BusinessEntityID
Group by CASE WHEN personid IS NOT NULL AND StoreID IS NOT NULL
THEN concat(store.name,'-',CONCAT(lastname,',',firstname,'',CASE WHEN middleName IS
NULL
THEN '' WHEN len(middlename) = 1 THEN concat(middlename,'.') when len(middlename)>1
then middlename ELSE 'Error'
end)) when personid IS NOT NULL AND StoreID IS NULL
THEN Store.Name
when personid IS NULL AND StoreID IS NOT NULL
THEN CONCAT(lastname,',',firstname,'',CASE WHEN middleName IS NULL
THEN ''
WHEN len(middlename) = 1
THEN concat(middlename,'.')
when len(middlename)>1
then middlename
ELSE 'Error'
End
Not clear what that bottom case is doing, but you can either replicate the CASE in the group by or even use a CROSS APPLY to reduce duplication
SELECT count(AccountNumber)
,CustomerType = CASE WHEN personid IS NOT NULL AND StoreID IS NOT NULL THEN 'Store with contact'
when personid IS NOT NULL AND StoreID IS NULL THEN 'store'
when personid IS NULL AND StoreID IS NOT NULL THEN 'Person'
ELSE 'Error'
end
FROM Sales.Customer AS c
LEFT JOIN Person.Person AS P ON c.PersonID = p.BusinessEntityID
LEFT JOIN Sales.Store ON c.StoreID = Store.BusinessEntityID
Group By CASE WHEN personid IS NOT NULL AND StoreID IS NOT NULL THEN 'Store with contact'
when personid IS NOT NULL AND StoreID IS NULL THEN 'store'
when personid IS NULL AND StoreID IS NOT NULL THEN 'Person'
ELSE 'Error'
end
Or with a CROSS APPLY
SELECT count(AccountNumber)
,CustomerType
FROM Sales.Customer AS c
LEFT JOIN Person.Person AS P ON c.PersonID = p.BusinessEntityID
LEFT JOIN Sales.Store ON c.StoreID = Store.BusinessEntityID
Cross Apply ( values ( CASE WHEN personid IS NOT NULL AND StoreID IS NOT NULL THEN 'Store with contact'
when personid IS NOT NULL AND StoreID IS NULL THEN 'store'
when personid IS NULL AND StoreID IS NOT NULL THEN 'Person'
ELSE 'Error'
end
) ) D(CustomerType)
Group By CustomerType
Related
I have a table like the below
Opp_ID Role_Name Role_User_Name
---------------------------------------
1 Lead Person_one
1 Developer Person_two
1 Developer Person_three
1 Owner Person_four
1 Developer Person_five
I now need to split the Role_Name column to be 3 different columns based on the values. I need to make sure there are no NULL values so the table should like the below
Opp_ID Lead Developer Owner
--------------------------------------------------
1 Person_one Person_two Person_four
1 Person_one Person_three Person_four
1 Person_one Person_five Person_four
My code is currently:
SELECT
ID,
CASE WHEN Role_Name = 'Lead' THEN Role_User_Name ELSE NULL END AS Lead,
CASE WHEN Role_Name = 'Developer' THEN Role_User_Name ELSE NULL END AS Developer,
CASE WHEN Role_Name = 'Owner' THEN Role_User_Name ELSE NULL END AS Owner
FROM
[table1]
WHERE
Role_Name IN ('Lead','Developer','Owner')
Unfortunately this returns these results:
Opp_ID Lead Developer Owner
-------------------------------------------
1 Person_one NULL NULL
1 NULL Person_two NULL
1 NULL Person_three NULL
1 NULL NULL Person_four
1 NULL Person_five NULL
I assume to get this working you need to join the code back on itself but I can't seem to get it working.
To apply each developer and lead across your owners for an Opp_ID, you'll want something like:
SELECT o.opp_id
, o.Role_User_Name AS Owner
, l.Role_User_Name AS Lead
, d.Role_User_Name AS Developer
FROM t1 AS o
LEFT OUTER JOIN t1 l ON o.opp_id = l.opp_id AND l.Role_Name = 'Lead'
LEFT OUTER JOIN t1 d ON o.opp_id = d.opp_id AND d.Role_Name = 'Developer'
WHERE o.Role_Name = 'Owner'
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=da4daea062534245bed474f93ffafbb7
You can just switch to aggregation:
SELECT ID,
MAX(CASE WHEN Role_Name = 'Lead' THEN Role_User_Name END) AS Lead,
MAX(CASE WHEN Role_Name = 'Developer' THEN Role_User_Name END) AS Developer,
MAX(CASE WHEN Role_Name = 'Owner' THEN Role_User_Name END) AS Owner
FROM [table1]
WHERE Role_Name IN ('Lead', 'Developer', 'Owner')
GROUP BY ID;
If you could have multiple people, you might want to use STRING_AGG().
Note that I removed the ELSE NULL. This is redundant. With no ELSE clause, the CASE expression returns NULL when there is no match.
You can also use first_value function on Pivot results like below
See working demo
select
opp_id,
lead=COALESCE([lead],FIRST_VALUE([Lead]) over( order by opp_id )),
Developer=COALESCE([Developer],FIRST_VALUE([Developer]) over( order by opp_id )),
Owner=COALESCE([Owner],FIRST_VALUE([Owner]) over( order by opp_id ))
from
(select opp_id,Role_Name,
Role_User_Name,
rn=row_number() over( partition by Role_Name order by (select 1))
from
table1)
src
pivot
(max(Role_user_name) for role_name in ([Lead],[Developer],[Owner]))p
I prefer to use cross join
select o.opp_id,
o.role_user_name o,
l.role_user_name l,
d.role_user_name d
from t1 o cross join t1 l cross join t1 d
where o.role_name = 'Owner'
and l.role_name = 'Lead'
and d.role_name = 'Developer'
enter image description here
Ok So this is the second time i'm trying to fix this.
I was wondering if there is a possible way to optimize the cursor created for a stored procedure, used to iterate through a big select statement with two unions. In which later on, the stored procedure begins inserting values to a staging table checking each value against a "where not exist" select statement.
Or better yet, is it possible to create all this with a select statement and possibly joins.
The inserting process takes far too long to complete, and I would recon selecting the data would be much faster.
Here is an example of the SQL:
declare #ID1 varchar(40) ,
#ID2 varchar(20) ,
#State varchar(20) ,
#isActive bit
Declare CuTable SCROLL INSENSITIVE cursor for
Select
Cast(ID1 as Varchar(20)) AS ID1,
Cast(ID2 as Varchar(20)) AS ID2,
'AT' AS [State],
CASE When (isAvtiveDate > { fn CURDATE() }) or isAvtiveDate is null Then 1 else 0 end AS isAvtive
From
server1.db.dbo.table1
Inner Join
server1.db.dbo.table2 on ID2 = ID1
Where ID3 = 1 AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
UNION
Select
Cast(ID1 as Varchar(20)) AS ID1,
Cast(ID2 as Varchar(20)) AS ID2,
'AP' AS [State],
CASE When (isActiveDate > { fn CURDATE() }) or isActiveDate is null Then 1 else 0 end AS isActive
From
server1.db.dbo.table1
Inner Join
server1.db.dbo.table2 on ID2 = ID1
Where
ID3 = 2 AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
UNION
Select
Cast(ID1 as Varchar(20)) AS ID1,
Cast(ID2 as Varchar(20)) AS ID2,
'AH' AS [State],
CASE When (isActiveDate > { fn CURDATE() }) or isActiveDate is null Then 1 else 0 end AS isActive
From server1.db.dbo.table1 inner join server1.db.dbo.table2 on ID2 = ID1
inner join server1.db.dbo.table13 on ID2 = ID4
Where ID3 = 5 and toDate is null and fromDate is not null AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
Open CuTable
Fetch Next From CuTable Into #ID1, #ID2, #[State], #isActive
While ##Fetch_Status = 0
Begin
Insert Into StagingTable (ID1, ID2, [State], isActive)
--Values
Select #ID1, #ID2, #[State], #isActive
where not exists(select * from StagingTable where ID1 = #ID1 and ID2 = #ID2)
Fetch Next From CuTable Into #ID1, #ID2, #[State], #isActive
End
close CuTable
deallocate CuTable
HEADS UP: I'm using SQL SERVER 2005
UPDATE regarding Leonidas199x comment thread:
Don't think you need a cursor at all, as the data is not dynamically changing. You should be able to do this with a set based approach. Below is an example using CTE, with a left join to only insert those that do not exist in the staging table:
;WITH CTE AS
(
SELECT CAST(ID1 as Varchar(20)) AS ID1,
CAST(ID2 as Varchar(20)) AS ID2,
'AT' AS [State],
CASE When (isAvtiveDate > { fn CURDATE() }) or isAvtiveDate is null Then 1 else 0 end AS isAvtive
FROM server1.db.dbo.table1
INNER JOIN server1.db.dbo.table2 on ID2 = ID1
WHERE ID3 = 1 AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
UNION
SELECT CAST(ID1 as Varchar(20)) AS ID1,
CAST(ID2 as Varchar(20)) AS ID2,
'AP' AS [State],
CASE WHEN (isActiveDate > { fn CURDATE() }) or isActiveDate is null Then 1 else 0 end AS isActive
FROM server1.db.dbo.table1
INNER JOIN server1.db.dbo.table2 on ID2 = ID1
WHERE ID3 = 2 AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
UNION
SELECT
Cast(ID1 as Varchar(20)) AS ID1,
Cast(ID2 as Varchar(20)) AS ID2,
'AH' AS [State],
CASE When (isActiveDate > { fn CURDATE() }) or isActiveDate is null Then 1 else 0 end AS isActive
FROM server1.db.dbo.table1
INNER JOIN server1.db.dbo.table2 ON ID2 = ID1
INNER JOIN server1.db.dbo.table13 ON ID2 = ID4
WHERE ID3 = 5 and toDate is null and fromDate is not null AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
)
INSERT INTO StagingTable
(
ID1,
ID2,
[State],
isActive
)
SELECT DISTINCT
CT.ID1,
CT.ID2,
CT.[State],
CT.isActive
FROM CTE AS CT
LEFT JOIN StagingTable AS ST ON ST.ID1 = CT.ID1 AND ST.ID2 = CT.ID2
WHERE ST.ID1 IS NULL
AND ST.ID2 IS NULL;
Given the requirement to check each row as the cursor does, I would use the following, using a temp table to check each set of ID1 and ID2 that are identified are unique when inserting into the temp table, then do the insert to the staging table from the temp table:
/*Create temp table*/
IF OBJECT_ID('tempdb..#tmpData') IS NOT NULL DROP TABLE #tmpData
GO
CREATE TABLE #tmpData
(
ID1 VARCHAR(20) ,
ID2 VARCHAR(20) ,
[State] VARCHAR(2) ,
IsActiveData BIT
)
/*Insert into the temp table, with each insert join back to the temp table to ensure ID1 and ID2 are not already inserted*/
INSERT INTO #tmpData
(
ID1 ,
ID2 ,
[State] ,
IsActiveData
)
SELECT CAST(ID1 as Varchar(20)) AS ID1,
CAST(ID2 as Varchar(20)) AS ID2,
'AT' AS [State],
CASE WHEN (isAvtiveDate > { fn CURDATE() }) or isAvtiveDate is null Then 1 else 0 end AS isAvtive
FROM server1.db.dbo.table1
INNER JOIN server1.db.dbo.table2 on ID2 = ID1
WHERE ID3 = 1 AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
INSERT INTO #tmpData
(
ID1 ,
ID2 ,
[State] ,
IsActiveData
)
SELECT CAST(T1.ID1 as VARCHAR(20)) AS ID1,
CAST(T2.ID2 as VARCHAR(20)) AS ID2,
'AP' AS [State],
CASE WHEN (isActiveDate > { fn CURDATE() }) or isActiveDate is null Then 1 else 0 end AS isActive
FROM server1.db.dbo.table1 AS T1
INNER JOIN server1.db.dbo.table2 AS T2 ON T2.ID2 = T1.ID1
LEFT JOIN #tmpData AS T ON T.ID1 = T1.ID1 AND T.ID2 = T2.ID2
WHERE ID3 = 2 AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
AND T.ID1 IS NULL
AND T.ID2 IS NULL
INSERT INTO #tmpData
(
ID1 ,
ID2 ,
[State] ,
IsActiveData
)
SELECT
Cast(T1.ID1 as Varchar(20)) AS ID1,
Cast(T2.ID2 as Varchar(20)) AS ID2,
'AH' AS [State],
CASE When (isActiveDate > { fn CURDATE() }) OR isActiveDate IS NULL Then 1 else 0 end AS isActive
FROM server1.db.dbo.table1 AS T1
INNER JOIN server1.db.dbo.table2 AS T2 ON T2.ID2 = T1.ID1
INNER JOIN server1.db.dbo.table13 AS T13 ON T2.ID2 = T13.ID4
LEFT JOIN #tmpData AS T ON T.ID1 = T1.ID1 AND T.ID2 = T2.ID2
WHERE ID3 = 5
AND toDate IS NULL
AND fromDate IS NOT NULL
AND isActiveDate <= ISNULL(isActiveDate,'2020-01-01')
AND T.ID1 IS NULL
AND T.ID2 IS NULL
/*Insert into the staging table from the temp table ensuring only records that are not already in there are inserted.*/
INSERT INTO StagingTable
(
ID1,
ID2,
[State],
isActive
)
SELECT CT.ID1,
CT.ID2,
CT.[State],
CT.isActive
FROM #tmpData AS CT
LEFT JOIN StagingTable AS ST ON ST.ID1 = CT.ID1 AND ST.ID2 = CT.ID2
WHERE ST.ID1 IS NULL
AND ST.ID2 IS NULL;
I have a SQL query that is just a union between two SELECT statements. Say the result of the overall query produces 10 records. I want as part of that result set a column that is a numeric and sequential (like a primary key - 0,1,2,3, and so on). My problem is the way I have this coded, as you can see below, doesn't produce unique values (the 0 value is repeated twice, the 1 value is repeated twice, as expected, because of the union statement). How can I get the below "Transaction Sequence Number" to display 1,2,3,4,5,6,7,8,9,10? Instead of 1,2,3,4,5,1,2,3,4,5?
Here's my code (below). I will be posting a screenshot of my result set shortly - SQL Server is being incredibly slow for me right now - I hope this makes sense without a screenshot of the result set:
select top 5
'ACCT PROMORESP' as 'Transaction Identifier',
row_number() over (order by s.HL_ACCT_ID) as 'Transaction Sequence Number',
s.HL_ACCT_ID as 'HL_Acct_ID',
null as [AcctNumber],
null as [AcctType],
null as [AcctSource],
null as [DUNS_NBR],
null as [DBPLCR_CONTACT_ID],
s.CAMPAIGNCODE as [CellCode],
'-1' as [OfferCode],
case
when c.EventDate is not null then 'Click'
when c.EventDate is null then
case
when sub.status = 'unsubscribed' then 'Unsubscribe'
when sub.status = 'bounced' then 'Bounce'
when sub.status = 'held' then 'Bounce'
end
end as [ResponseType],
convert(varchar, c.EventDate, 112) as [ResponseDate],
null as [ResponseQuantity],
null as [ResponseValue],
'Email' as [ResponseChannel],
null as [Cookie ID],
null as [IP address],
null as [Device ID],
null as [CUSTOM_TEXT_01],
null as [CUSTOM_TEXT_02],
null as [CUSTOM_TEXT_03],
null as [CUSTOM_TEXT_04],
null as [CUSTOM_TEXT_05]
from cXXXXXXX.sendlog s with (nolock)
inner join cXXXXXXX._subscribers sub with (nolock) on sub.SubscriberKey = s.Email
left join cXXXXXXX._click c with (nolock) on c.JobID = s.JobID and c.SubscriberKey = s.Email
where c.EventDate is not null or (c.EventDate is null and (sub.status = 'unsubscribed' or sub.status = 'bounced' or sub.status = 'held')) and c.isunique = 1
union all
select top 5
'ACCT PROMORESP' as 'Transaction Identifier',
(row_number() over (order by s.HL_ACCT_ID)) + 1 as 'Transaction Sequence Number',
s.HL_ACCT_ID as 'HL_Acct_ID',
null as [AcctNumber],
null as [AcctType],
null as [AcctSource],
null as [DUNS_NBR],
null as [DBPLCR_CONTACT_ID],
s.CAMPAIGNCODE as [CellCode],
'-1' as [OfferCode],
case
when o.EventDate is not null then 'Message Open'
when o.EventDate is null then
case
when sub.status = 'unsubscribed' then 'Unsubscribe'
when sub.status = 'bounced' then 'Bounce'
when sub.status = 'held' then 'Bounce'
end
end as [ResponseType],
convert(varchar, o.EventDate, 112) as [ResponseDate],
null as [ResponseQuantity],
null as [ResponseValue],
'Email' as [ResponseChannel],
null as [Cookie ID],
null as [IP address],
null as [Device ID],
null as [CUSTOM_TEXT_01],
null as [CUSTOM_TEXT_02],
null as [CUSTOM_TEXT_03],
null as [CUSTOM_TEXT_04],
null as [CUSTOM_TEXT_05]
from cXXXXXXX.sendlog s with (nolock)
inner join cXXXXXXX._subscribers sub with (nolock) on sub.SubscriberKey = s.Email
left join cXXXXXXX._open o with (nolock) on o.JobID = s.JobID and o.SubscriberKey = s.Email
where o.EventDate is not null or (o.EventDate is null and (sub.status = 'unsubscribed' or sub.status = 'bounced' or sub.status = 'held')) and o.isunique = 1
You can enclose your sql in a common table expression and then number them:
;WITH CTE AS(your sql...)
SELECT *,
(row_number() over (order by HL_ACCT_ID)) + 1 as 'Transaction Sequence Number'
FROM CTE
You have to make sure you have unique column names in the cte. Also, if you are using this sql statement with other statements, make sure you add a ';' before it or end the previous statement with a ';'.
Try using this.
SELECT ROW_NUMBER() OVER(ORDER BY DATA.HL_ACCT_ID),DATA.* FROM
(your query here...)DATA
I have 3 columns to base my JOIN on -> ID, Account, Cust. There can be multiple rows containing the same ID value.
I want to prioritise my JOIN on 1) ID, 2) Account, 3) Cust.
So in the example below, the UserCode that should be populated in #UserData should be 'u11z' as all columns contain a value.
How do I do this? Below my code to date...
UPDATE #UserData
SET UserCode = ur.UserCode
FROM #UserData uA
INNER JOIN UserReference ur
ON uA.ID = ur.ID
AND ((ua.Account = ur.Account) OR (ur.Account = ur.Account))
AND ((ua.Cust = ur.Cust) OR (ur.Cust = ur.Cust))
UserReference TABLE:
Cust Account ID UserCode
234 NULL 9A2346 u12x
234 Test 9A2346 u11z
NULL NULL 9A2346 u30s
#UserData TABLE:
Cust Account ID UserCode
234 Test 9A2346 NULL
Thanks!
You can try the following. I joined tables, counted the number of matches, and ranked them. Then select rank 1.
; with userCte (userCodeA, userCodeB, rank)
as
(
select a.usercode, b.usercode,
rank() over (partition by a.id order by case when a.cust = b.cust then 1 else 0 end +
case when a.account = b.account then 1 else 0 end +
case when a.id = b.id then 1 else 0 end desc) as rank
from userdata a
join userreference b
on a.id = b.id or a.account = b.account or a.id = b.id
)
select * from userCte
--update userCte
--set userCodeA = userCodeB
where rank = 1
Is this what you want? It is difficult to understand what you are asking for.
USE tempdb;
CREATE TABLE UserReference
(
ID VARCHAR(255) NULL
, Account VARCHAR(255) NULL
, Cust INT NULL
, UserCode VARCHAR(255)
);
INSERT INTO UserReference VALUES ('9A2346', NULL, 234, 'A');
INSERT INTO UserReference VALUES ('9A2346', 'TEST', 234, 'B');
INSERT INTO UserReference VALUES ('9A2346', NULL, NULL, 'C');
DECLARE #UserData TABLE
(
ID VARCHAR(255) NULL
, Account VARCHAR(255) NULL
, Cust INT NULL
, UserCode VARCHAR(255)
);
INSERT INTO #UserData
SELECT UR.ID, UR.Account, UR.Cust, NULL
FROM dbo.UserReference UR;
UPDATE #UserData
SET UserCode = ur.UserCode
FROM #UserData uA
INNER JOIN UserReference ur
ON uA.ID = ur.ID
AND ua.Account = ur.Account
AND ua.Cust = ur.Cust;
SELECT *
FROM #UserData;
Results of the last SELECT :
If I understood your question correctly...
And if any col in a row having a null value will drop the priority then you can use a query something like below to check the count of null values in a row, this might not be a complete answer, but a possible approach...
SELECT count(*)
FROM TableName
WHERE Col1 IS NULL and Col2 is null
My objective is to have one record with both HomeNumber & OfficeNumber and I'm keeping the PersonID to reference the customer table. I'm thinking I shouldn't even be using a UNION but maybe a select query from two nested sub queries.
The results returned look like this.
1A370535-9432-45B9-8F08-004F040EE196 '' ''
1A370535-9432-45B9-8F08-004F040EE196 6127319561 ''
E8FA1667-416C-4639-ADDC-02143D651B4E '' 6512096719
E8FA1667-416C-4639-ADDC-02143D651B4E 6515786963 ''
Here my query:
SELECT PhoneNumbers.PersonID, PhoneNumbers.HomeNum, PhoneNumbers.OfficeNum
FROM (
SELECT PhoneHub.PersonID, ISNULL(PhoneHub.PhoneNbr, '') AS HomeNum, '' AS OfficeNum
FROM
--PhoneType INNER JOIN
PhoneHub --ON PhoneType.ID = PhoneHub.TypeID
WHERE
(PhoneHub.FranID = #FranID) AND
(PhoneHub.TypeID = '28321161-668e-4a56-90be-67a146fa1353') -- Home# ID
UNION
SELECT PhoneHub.PersonID, '' AS HomeNum, ISNULL(PhoneHub.PhoneNbr, '') AS OffNum
FROM
--PhoneType AS PhoneType_2 INNER JOIN
PhoneHub --AS PhoneHub ON PhoneType_2.ID = PhoneHub.TypeID
WHERE
(PhoneHub.FranID = #FranID) AND
(PhoneHub.TypeID = '02a4125b-b968-4dc6-9734-7f75f45f7635') --Office# ID
) AS PhoneNumbers
ORDER BY PhoneNumbers.PersonID
Table Schema - PhoneHub
PK ID uniqueidentifier
FK FranID uniqueidentifier Franchise.ID
FK PersonID uniqueidentifier Customer.ID
FK TypeID uniqueidentifier PhoneType.ID
PhoneNbr nvarchar(20)
PhoneExt nvarchar(10)
IsDefault bit
This looks like a pivot requirement.
SELECT PersonID,
Max(case when TypeID = '28321161-668e-4a56-90be-67a146fa1353'
then PhoneNbr End) HomeNum,
Max(case when TypeID = '02a4125b-b968-4dc6-9734-7f75f45f7635'
then PhoneNbr End) OfficeNum
FROM
PhoneHub
WHERE
PhoneHub.FranID = #FranID
GROUP BY PersonID
Select a.PersonID,Coalesce(home.PhoneNbr, '') AS HomeNum,Coalesce(office.PhoneNbr, '') AS OffNum from
(
SELECT PhoneHub.PersonID
FROM
PhoneHub
WHERE
(PhoneHub.FranID = #FranID) AND
(PhoneHub.TypeID = '28321161-668e-4a56-90be-67a146fa1353')
UNION
SELECT PhoneHub.PersonID
FROM
PhoneHub
WHERE
(PhoneHub.FranID = #FranID) AND
(PhoneHub.TypeID = '02a4125b-b968-4dc6-9734-7f75f45f7635')
) as a
left join PhoneHub home on (home.PersonID = a.PersonID) and (home.FranID = #FranID) AND (home.TypeID = '28321161-668e-4a56-90be-67a146fa1353')
left join PhoneHub office on (office.PersonID = a.PersonID) and (office.FranID = #FranID) AND (office.TypeID = '02a4125b-b968-4dc6-9734-7f75f45f7635')
order by a.PersonID