SQL Removing Duplicate Result with Left Join - sql

I've got code that if pulling info from two different tables, and I'm getting duplicates. I've tried DISTINCT in the SELECT statement, but I get lots of errors "ntext data type cannot be selected as DISTINCT because it is not comparable."
So my next attempt was to try GROUP BY, but I get errors "Column Person.Pers_FirstName is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
So my records have multiple relationship fields, but it's a problem because some records have none, one or more than one relationship (the options are NULL, project engineer, project owner, or project contractor). Current code only shows NULL and Project Engineer, but if there's records with the other two then they are excluded. If I include the other relationship descriptions then I get duplicates.
SELECT
RTRIM(ISNULL(Pers_FirstName, '')) + ' ' + RTRIM(ISNULL(Pers_LastName, '')) AS Pers_FullName,
RTRIM(ISNULL(oppocomp.Comp_PhoneCountryCode, '')) + ' ' + RTRIM(ISNULL(oppocomp.Comp_PhoneAreaCode, '')) + ' ' + RTRIM(ISNULL(oppocomp.Comp_PhoneNumber, '')) AS Comp_PhoneFullNumber,
RTRIM(ISNULL(oppocomp.Comp_FaxCountryCode, '')) + ' ' + RTRIM(ISNULL(oppocomp.Comp_FaxAreaCode, '')) + ' ' + RTRIM(ISNULL(oppocomp.Comp_FaxNumber, '')) AS Comp_FaxFullNumber,
RTRIM(ISNULL(Pers_PhoneCountryCode, '')) + ' ' + RTRIM(ISNULL(Pers_PhoneAreaCode, '')) + ' ' + RTRIM(ISNULL(Pers_PhoneNumber, '')) AS Pers_PhoneFullNumber,
RTRIM(ISNULL(Pers_FaxCountryCode, '')) + ' ' + RTRIM(ISNULL(Pers_FaxAreaCode, '')) + ' ' + RTRIM(ISNULL(Pers_FaxNumber, '')) AS Pers_FaxFullNumber,
Opportunity.*, oppocomp.Comp_Name, oppocomp.Comp_Territory, oppocomp.Comp_EmailAddress,
oppocomp.Comp_CompanyId, oppocomp.Comp_SecTerr, oppocomp.Comp_CreatedBy,
oppocomp.Comp_PrimaryUserID, Terr_Caption, Pers_Title, Pers_EmailAddress, Pers_SecTerr,
Pers_CreatedBy, Pers_PersonId, Pers_PrimaryUserID, Chan_Description,
oppocomp.Comp_ChannelID, (Oppo_Base_Currency.Curr_CurrencyID) AS Oppo_WeightedForecast_CID,
Pers_ChannelID ((Oppo_Forecast / Oppo_Forecast_Currency.Curr_Rate) * Oppo_Certainty / 100) AS Oppo_WeightedForecast,
Oppo_PrimaryAccountId AS Acc_AccountId, rend_Notes, renl_description,
relcomp.Comp_Name AS Rela_CompanyName
FROM Opportunity
LEFT JOIN Person ON Oppo_PrimaryPersonID = Pers_PersonID
LEFT JOIN Company AS oppocomp ON Oppo_PrimaryCompanyID = Comp_CompanyId
LEFT JOIN Territories ON Oppo_SecTerr = Terr_TerritoryId
LEFT JOIN Channel ON Chan_ChannelId = Oppo_ChannelId
LEFT JOIN RelatedEntityData ON Oppo_OpportunityId = rend_entity1id
LEFT JOIN RelatedEntityLinks ON rend_relatedentitylinkid = REnL_RelatedEntityLinkID
LEFT JOIN Company AS relcomp ON rend_entity2id = relcomp.Comp_CompanyId
LEFT JOIN Currency Oppo_Forecast_Currency ON Oppo_Forecast_CID = Oppo_Forecast_Currency.Curr_CurrencyID
LEFT JOIN Currency Oppo_Base_Currency
ON Oppo_Base_Currency.Curr_CurrencyID = (
SELECT CAST(CAST(Parm_Value AS NCHAR) AS INTEGER)
FROM Custom_SysParams
WHERE Parm_Name = 'BaseCurrency'
)
WHERE Oppo_Deleted IS NULL
AND (renl_description IS NULL OR renl_description = 'Project Engineer')

Related

some weird signs appearing on SQL SERVER Query output

i have written a SELECT Query on SQL SERVER 2014 . I have got the desired output . but an apostrophe symbol(') appearing on 'TaskAction' field data(at the end of each data). here it is my script:
SELECT
WOtask.PK,
WOPK,
TaskNo,
TaskAction =
CASE
WHEN WOTask.AssetPK IS NOT NULL THEN '<b>' + Asset.AssetName + ' [' + Asset.AssetID + ']</b> ' + CASE
WHEN Asset.Vicinity IS NOT NULL AND
Asset.Vicinity <> '''' THEN RTRIM(Asset.Vicinity) + ': '
ELSE ''''
END + WOtask.TaskAction + CASE
WHEN CONVERT(varchar, ValueLow) IS NOT NULL AND
CONVERT(varchar, ValueHi) IS NOT NULL AND
Spec = 1 THEN ' (Range: '' + CONVERT(VARCHAR,CONVERT(FLOAT,ISNULL(ValueLow,0))) + '' - '' + CONVERT(VARCHAR,CONVERT(FLOAT,ISNULL(ValueHi,0))) + )'
ELSE ''''
END
ELSE WOtask.TaskAction + CASE
WHEN CONVERT(varchar, ValueLow) IS NOT NULL AND
CONVERT(varchar, ValueHi) IS NOT NULL AND
Spec = 1 THEN ' (Range: '' + CONVERT(VARCHAR,CONVERT(FLOAT,ISNULL(ValueLow,0))) + '' - '' + CONVERT(VARCHAR,CONVERT(FLOAT,ISNULL(ValueHi,0))) + )'
ELSE ''''
END
END,
Rate,
Measurement,
Initials,
Fail,
Complete,
Header,
LineStyle,
WOtask.Comments,
WOtask.NotApplicable,
WOTask.Photo1,
WOTask.Photo2
FROM WOtask WITH (NOLOCK)
LEFT OUTER JOIN Asset WITH (NOLOCK)
ON Asset.AssetPK = WOTask.AssetPK
LEFT OUTER JOIN AssetSpecification
ON AssetSpecification.PK = WOTask.AssetSpecificationPK
WHERE (WOPK IN (SELECT
WOPK
FROM WO WITH (NOLOCK)
LEFT OUTER JOIN Asset WITH (NOLOCK)
ON Asset.AssetPK = WO.AssetPK
LEFT OUTER JOIN AssetHierarchy WITH (NOLOCK)
ON AssetHierarchy.AssetPK = WO.AssetPK
WHERE WO.WOPK = 10109)
)
ORDER BY WOPK, TaskNo
now please check my output and error
please help to solve this issue. Thanks in Advance.
As noted in comments, use ELSE '' instead of ELSE ''''. The reason is that within a pair of single quotes, then '' tells SQL to escape a single quote into your output.
For instance, to show the output User's, you would need SELECT 'User''s'.

How to reduce execution time of SQL Select Query

TitemName and TshotName is the problem here
SELECT DISTINCT
tJobs.* ,
tCustomer.Name AS Customer_name ,
(SELECT tEmployee.First + ' ' + tEmployee.Last
FROM tEmployee
WHERE tEmployee.EmployeeID = tJobs.AccountExecutiveID) AS AccountExecutive,
(SELECT tEmployee.First + ' ' + tEmployee.Last
FROM tEmployee
WHERE tEmployee.EmployeeID = tJobs.AccountManagerID) AS AccountManager,
dbo.RetrunUserFavourite(tJobs.JobNumber, 33369, 'Employee') AS Favorites,
(SELECT COUNT(*)
FROM tShots
WHERE tShots.JobNumber = tJobs.JobNumber) AS shotcount,
SUBSTRING((SELECT ', ' + SKU + ', ' + Source + ', ' + ModelNumber
+ ', ' + Description
FROM tItems
WHERE tItems.CustomerID = tCustomer.CustomerID
FOR XML PATH('')), 3, 200000) titemName,
SUBSTRING((SELECT ', ' + ArtDirection + ', '
+ REPLACE(CONVERT(VARCHAR(5), AdDate, 110), '-',
'/')
FROM tShots
WHERE tShots.JobNumber = tJobs.JobNumber
FOR XML PATH('')), 3, 200000) TshotName
FROM
tJobs
INNER JOIN
tCustomer ON tCustomer.CustomerID = tJobs.CustomerID
WHERE
tCustomer.CustomerID = 68666
I strongly agree with M Ali's comments. Two points I would make. The first is not with regard to performance. But, instead of substring() use:
STUFF((SELECT ', ' + SKU + ', ' + Source + ', ' + ModelNumber+ ', ' + Description
FROM tItems
WHERE tItems.CustomerID = tCustomer.CustomerID
FOR XML PATH('')
), 1, 1, '') as titemName
That way, you don't need strange, meaningless numbers floating around the code.
Second, you may need indexes. Based on the highlighted performance problems, I would suggest:
tItems(CustomerID)
and:
tshots(JobNumber, ArtDirection, AdDate)
You have awful lot of string manipulation going on is your query, anyway a slightly improved version of your query would look something like...
Select DISTINCT
tJobs.*
, tCustomer.Name AS Customer_name
, AE.First + ' ' + AE.Last AS AccountExecutive
, AM.First + ' ' + AM.Last AS AccountManager
, dbo.RetrunUserFavourite(tJobs.JobNumber,33369,'Employee')AS Favorites
, TS.shotcount
, SUBSTRING(( SELECT ', ' + SKU + ', ' + Source + ', ' + ModelNumber+ ', ' + Description
FROM tItems
where tItems.CustomerID=tCustomer.CustomerID
FOR XML PATH('')), 3, 200000)titemName
, SUBSTRING(( SELECT ', ' + ArtDirection +', '+REPLACE(CONVERT(VARCHAR(5),AdDate,110), '-','/')
FROM tShots
where tShots.JobNumber=tJobs.JobNumber
FOR XML PATH('')), 3, 200000)TshotName
From tJobs
inner join tCustomer on tCustomer.CustomerID = tJobs.CustomerID
Left join tEmployee AE ON AE.EmployeeID = tJobs.AccountExecutiveID
Left join tEmployee AM ON AM.EmployeeID = tJobs.AccountManagerID
Left join (
SELECT JobNumber , Count(*) shotcount
FROM tShots
GROUP BY JobNumber
) TS ON TS.JobNumber = tJobs.JobNumber
WHERE tCustomer.CustomerID = 68666
A Couple of Pointers:
Having sub-queries in your select statement makes it very inefficient, because the sub-query is executed for each row returned by the outer query, a more sensible way of doing it would be to use joins.
You Also have a call to a User-Defined Scalar function dbo.RetrunUserFavourite() in your select , these scalar UDFs are also performance killers, again the same execution logic is applied here, they are also executed for each row returned by the outer query, a more sensible way would be to put the function logic/code inside a CTE and join your query to that CTE.
These comma delimited lists that you are creating on the fly for last two columns will be slow, maybe an Inline-Table-Valued function can give better performance here.

Sql - How to add condition on fields when inserting them into a table?

I need to insert strings in an sql table, where I have to add condition. For example:
SELECT ii.Terminating_Item_Site_ID,
ii.Originating_Item_Site_ID,
loc.ServiceAddress,
loc.ServiceCity,
loc.ServiceState,
(ii.Originating_Item_Site_ID + ' - ' + loc.ServiceAddress + ', ' + loc.ServiceCity + ', ' + loc.ServiceState) AS OrigSite
FROM tblItemInventory ii
LEFT OUTER JOIN tblServiceLocation AS loc ON loc1.ServiceLocationID = ii.Originating_Item_Site_ID
I need to put a condition when inserting the field OrigSite, so if ii.Originating_Item_Site_ID or loc.ServiceAddress or loc.ServiceCity or loc.ServiceState is null, I don't need to include it so I replace it with ''.
What is happening is that if any of the above fields is null, OrigSite is becoming null as well.
I have tried to use WHEN but I couldn't manage it.
I am using SQL Server 2008 R2.
Can anyone help?
When you concatenate string and 1 of the string is null the concatenated result is also null. You can use isnull('string','') on each part to avoid that behavior. Here is the code example:
SELECT ii.Terminating_Item_Site_ID,
ii.Originating_Item_Site_ID,
loc.ServiceAddress,
loc.ServiceCity,
loc.ServiceState,
(ISNULL(ii.Originating_Item_Site_ID,'')
+ ' - ' + ISNULL(loc.ServiceAddress,'')
+ ', ' + ISNULL(loc.ServiceCity,'')
+ ', ' + ISNULL(loc.ServiceState,'')) AS OrigSite
FROM tblItemInventory ii
LEFT OUTER JOIN tblServiceLocation AS loc ON loc1.ServiceLocationID = ii.Originating_Item
SELECT ii.Terminating_Item_Site_ID,
coalesce(ii.Originating_Item_Site_ID,''),
coalesce(loc.ServiceAddress,''),
coalesce(loc.ServiceCity,''),
coalesce(loc.ServiceState,''),
(coalesce(ii.Originating_Item_Site_ID,'') + ' - ' + coalesce(loc.ServiceAddress,'') + ', ' + coalesce(loc.ServiceCity,'') + ', ' + coalesce(loc.ServiceState,'')) AS OrigSite
FROM tblItemInventory ii
LEFT OUTER JOIN tblServiceLocation AS loc ON loc1.ServiceLocationID = ii.Originating_Item_Site_ID
ISNULL is a system function that replaces null values with a predifined value.
Colasce is another one like ISNULL But Coalesce is a part of standard sql.
ISNULL is T-sql specific.
Be more standard be more portable.
SELECT ii.Terminating_Item_Site_ID,
isnull(ii.Originating_Item_Site_ID,''),
isnull(loc.ServiceAddress,''),
isnull(loc.ServiceCity,''),
isnull(loc.ServiceState,''),
(isnull((ii.Originating_Item_Site_ID + ' - ' + isnull(loc.ServiceAddress,'') + ', ' + isnull(loc.ServiceCity,'') + ', ' + isnull(loc.ServiceState,'')) AS OrigSite
FROM tblItemInventory ii
LEFT OUTER JOIN tblServiceLocation AS loc ON loc1.ServiceLocationID = ii.Originating_Item_Site_ID

Case within Case when combining multiple columns into one

I'm trying to create a query that will take multiple columns in a View and bring it into one column in the query. The values from each column needs to be separated by '|' (pipe).
I've tried:
1) (expression1 + '|' + expression2) AS xxxx, but if one expression has a null value, it makes the results 'null'.
2) CAST (expression1 as varchar (10)) + '|' + CAST (expression2 as varchar (10)) AS xxxx, but get the same results.
3) CASE (expression1 is null) then (' ') else (expression1) +'|' + CASE (expression2 is null) then (' ') else (expression2) END AS xxxx, but I get a syntax error near the keyword 'AS'.
Here's the full query using CASE.
SELECT DISTINCT dbo.REG.BUILDING, dbo.REG.CURRENT_STATUS, dbo.REG_CONTACT.LOGIN_ID, dbo.REG.LAST_NAME
, CASE WHEN dbo.View_MYAccess_Period1.CRSGRP1 is null then ' ' else dbo.View_MYAccess_Period1.CRSGRP1 + ' |' +
CASE WHEN dbo.View_MYAccess_Period2.CRSGRP2 is null then ' ' else dbo.View_MYAccess_Period2.CRSGRP2
END AS CRSGRP
FROM dbo.REG_CONTACT RIGHT OUTER JOIN
dbo.REG_STU_CONTACT ON dbo.REG_CONTACT.CONTACT_ID = dbo.REG_STU_CONTACT.CONTACT_ID RIGHT OUTER JOIN
dbo.REG ON dbo.REG_STU_CONTACT.STUDENT_ID = dbo.REG.STUDENT_ID LEFT OUTER JOIN
dbo.View_MYAccess_Period1 ON dbo.REG.STUDENT_ID = dbo.View_MYAccess_Period1.STUDENT_ID LEFT OUTER JOIN
dbo.View_MYAccess_Period2 ON dbo.REG.STUDENT_ID = dbo.View_MYAccess_Period2.STUDENT_ID
Any help for this newbie would be greatly appreciated!
Use ISNULL function,
SELECT DISTINCT dbo.REG.BUILDING, dbo.REG.CURRENT_STATUS, dbo.REG_CONTACT.LOGIN_ID, dbo.REG.LAST_NAME
, ISNULL(dbo.View_MYAccess_Period1.CRSGRP1,' ') + ' |' +
ISNULL(dbo.View_MYAccess_Period2.CRSGRP2,' ') CRSGRP
FROM dbo.REG_CONTACT RIGHT OUTER JOIN
dbo.REG_STU_CONTACT ON dbo.REG_CONTACT.CONTACT_ID = dbo.REG_STU_CONTACT.CONTACT_ID RIGHT OUTER JOIN
dbo.REG ON dbo.REG_STU_CONTACT.STUDENT_ID = dbo.REG.STUDENT_ID LEFT OUTER JOIN
dbo.View_MYAccess_Period1 ON dbo.REG.STUDENT_ID = dbo.View_MYAccess_Period1.STUDENT_ID LEFT OUTER JOIN
dbo.View_MYAccess_Period2 ON dbo.REG.STUDENT_ID = dbo.View_MYAccess_Period2.STUDENT_ID
In example 1, you might use the COALESCE(expression, fallback) function to force expression to return a fallback value if the expression is null. (Then tweak the rest of the logic accordingly.)
In your example 3, you need another END keyword:
CASE
(expression1 is null) then (' ')
ELSE (expression1) +'|' +
CASE (expression2 is null) then (' ') else (expression2) END
END AS xxxx

UPDATE from inner complex SELECT

UPDATE DB4010.dbo.EntityStagedData
SET
EntityData = (
SELECT
geo.City + ' ' + geo.Description + ' ' + geo.Street + ' ' +
geo2.City + ' ' + geo2.Description + ' ' + geo2.Street
FROM DB4010.dbo.RouteTemplates templates
INNER JOIN DB4010.dbo.RouteTemplateClients clients
ON clients.RouteTemplateID = templates.RouteTemplateID
INNER JOIN DB4010.dbo.RouteTemplateStopMasters masters
ON masters.RouteTemplateClientID = clients.RouteTemplateClientID
INNER JOIN DB4010.dbo.RouteTemplateStopDetails details
ON details.RouteTemplateStopID = masters.PickupStopID
INNER JOIN DB4010.dbo.RouteTemplateStopDetails details2
ON details2.RouteTemplateStopID = masters.DeliveryStopID
INNER JOIN DB4010.dbo.Geofences geo
ON geo.GeofenceID = details.GeofenceID
INNER JOIN DB4010.dbo.Geofences geo2
ON geo2.GeofenceID = details2.GeofenceID
WHERE clients.RouteTemplateID = DB4010.dbo.EntityStagedData.EntityID
)
WHERE EXISTS ( SELECT RouteTemplateID FROM DB4010.dbo.RouteTemplates )
This is giving me an error:
Msg 515, Level 16, State 2, Line 1
Cannot insert the value NULL into
column 'EntityData', table 'DB4010.dbo.EntityStagedData'; column does
not allow nulls. UPDATE fails.
I can't, for the life of me, figure out how to update+Concatenate "EntityData" from the results of the inner Select statement...
I've made a few changes:
single-letter aliases for readability
fix to proprietary SQL Server UPDATE FROM syntax
elimination of uncorrelated WHERE EXISTS clause
You may still need to decide what to do in cases where geo.City etc. contain NULL values. You may need to simply wrap the expression in COALESCE or filter NULL rows out of the join altogether.
UPDATE s SET EntityData =
geo.City + ' ' + geo.Description + ' ' + geo.Street + ' ' +
geo2.City + ' ' + geo2.Description + ' ' + geo2.Street
FROM DB4010.dbo.EntityStagedData AS s
INNER JOIN DB4010.dbo.RouteTemplateClients AS c
ON c.RouteTemplateID = s.EntityID
INNER JOIN DB4010.dbo.RouteTemplates AS t
ON t.RouteTemplateID = c.RouteTemplateID
INNER JOIN DB4010.dbo.RouteTemplateStopMasters AS m
ON m.RouteTemplateClientID = c.RouteTemplateClientID
INNER JOIN DB4010.dbo.RouteTemplateStopDetails AS d
ON d.RouteTemplateStopID = m.PickupStopID
INNER JOIN DB4010.dbo.RouteTemplateStopDetails AS d2
ON d2.RouteTemplateStopID = m.DeliveryStopID
INNER JOIN DB4010.dbo.Geofences AS geo
ON geo.GeofenceID = d.GeofenceID
INNER JOIN DB4010.dbo.Geofences AS geo2
ON geo2.GeofenceID = d2.GeofenceID;
You can wrap the first section in a COALESCE statement as such:
SET EntityData = COALESCE(( SELECT geo.City + ' ' + geo.Description
+ ' ' + geo.Street + ' ' + geo2.City + ' ' + geo2.Description + ' '
+ geo2.Street
FROM DB4010.dbo.RouteTemplates templates
INNER JOIN DB4010.dbo.RouteTemplateClients clients ON clients.RouteTemplateID =
templates.RouteTemplateID
INNER JOIN DB4010.dbo.RouteTemplateStopMasters masters ON
masters.RouteTemplateClientID = clients.RouteTemplateClientID
INNER JOIN DB4010.dbo.RouteTemplateStopDetails details ON
details.RouteTemplateStopID = masters.PickupStopID
INNER JOIN DB4010.dbo.RouteTemplateStopDetails details2 ON
details2.RouteTemplateStopID = masters.DeliveryStopID
INNER JOIN DB4010.dbo.Geofences geo ON geo.GeofenceID = details.GeofenceID
INNER JOIN DB4010.dbo.Geofences geo2 ON geo2.GeofenceID = details2.GeofenceID
WHERE clients.RouteTemplateID = DB4010.dbo.EntityStagedData.EntityID ), '')
to set the value to a blank value.
If you want to get as much information as possible, wrap each individual portion in COALESCE statements to remove NULL values, such as:
SELECT COALESCE(geo.City, '') + ' ' + COALESCE(geo.Description, '') ...
That way, if one of your values in the sub-select is NULL, you won't get a NULL value as a result of the concatenation.