Sum like operation for strings in t-sql - tsql

I already have query to concatenate
DECLARE #ids VARCHAR(8000)
SELECT #ids = COALESCE(#ids + ', ', '') + concatenatedid
FROM #HH
but if I have to do it inline how can I do that? Any help please.
SELECT sum(quantity), COALESCE(#ids + ', ', '') + concatenatedid from #HH
Thanks.

Use the XML PATH trick. You may need a CAST
SELECT
SUBSTRING(
(
SELECT
',' + concatenatedid
FROM
#HH
FOR XML PATH ('')
)
, 2, 7999)
Also:
Join characters using SET BASED APPROACH (Sql Server 2005)
Subquery returned more than 1 value

Related

Best way to use multiple like statements in XML PATH query

When I use the "Or" operator (Secretary_Job_Title like '%Secretary%' or Secretary_Job_Title like '%Assistant%') I'm returning too many values.
How can I best use Like statement for Secretary and Assistant in the following query? Thanks in advance!!
SELECT STUFF((SELECT ';' + secretary
FROM [HandshakeProd].[dbo].[sp_attysecrel]
WHERE attorney = 'HC\' + Rtrim(p.EMPLOYEE_CODE)
AND secretary_job_title LIKE '%Secretary%'
FOR XML PATH('')), 1, 1, '') AS [Assistants]
Perhaps this is what you want?
SELECT STUFF((SELECT ';' + secretary
FROM [HandshakeProd].[dbo].[sp_attysecrel]
WHERE attorney = 'HC\' + Rtrim(p.EMPLOYEE_CODE)
AND (secretary_job_title LIKE '%Secretary%' OR secretary_job_title LIKE '%Assistant%')
FOR XML PATH('')), 1, 1, '') AS [Assistants]

PGSQL - Joining two tables on complicated condition

I got stuck during database migration on PostgreSQL and need your help.
I have two tables that I need to join: drzewa_mateczne.migracja (data I need to migrate) and ibl_as.t_adres_lesny (dictionary I need to join with migracja).
I need to join them on replace(drzewa_mateczne.migracja.adresy_lesne, ' ', '') = replace(ibl_as.t_adres_lesny.adres, ' ', ''). However my data is not very regular, so I want to join it on first good match with the dictionary.
I've created the following query:
select
count(*)
from
drzewa_mateczne.migracja a
where
length(a.adresy_lesne) > 0
and replace(a.adresy_lesne, ' ', '') = (select substr(replace(al.adres, ' ', ''), 1, length(replace(a.adresy_lesne, ' ', ''))) from ibl_as.t_adres_lesny al limit 1)
The query doesn't return any rows.
It does successfully join empty rows if ran without
length(a.adresy_lesne) > 0
The two following queries return rows (as expected):
select replace(adres, ' ', '')
from ibl_as.t_adres_lesny
where substr(replace(adres, ' ', ''), 1, 16) = '16-15-1-13-180-c'
limit 1
select replace(adresy_lesne, ' ', ''), length(replace(adresy_lesne, ' ', ''))
from drzewa_mateczne.migracja
where replace(adresy_lesne, ' ', '') = '16-15-1-13-180-c'
I'm suspecting that there might be a problem in sub-query inside the 'where' clause in my query. If you guys could help me resolve this issue, or at least point me in the right direction, I'd be very greatful.
Thanks in advance,
Jan
You can largely simplify to:
SELECT count(*)
FROM drzewa_mateczne.migracja a
WHERE a.adresy_lesne <> ''
AND EXISTS (
SELECT 1 FROM ibl_as.t_adres_lesny al
WHERE replace(al.adres, ' ', '')
LIKE (replace(a.adresy_lesne, ' ', '') || '%')
)
a.adresy_lesne <> '' does the same as length(a.adresy_lesne) > 0, just faster.
Replace the correlated subquery with an EXISTS semi-join (to get only one match per row).
Replace the complex string construction with a simple LIKE expression.
More information on pattern matching and index support in these related answers:
PostgreSQL LIKE query performance variations
Difference between LIKE and ~ in Postgres
speeding up wildcard text lookups
What you're basically telling the database to do is to get you the count of rows from drzewa_mateczne.migracja that have a non-empty adresy_lesne field that is a prefix of the adres field of a semi-random ibl_as.t_adres_lesny row...
Lose the "limit 1" in the subquery and substitute the "=" with "in" and see if that is what you wanted...

Using IndexOf and/Or Substring to parse data into separate columns

I am working on migrating data from one database to another for a hospital. In the old database, the doctor's specialty IDs are all in one column (swvar_specialties), each separated by commas. In the new database, each specialty ID will have it's own column (example: Specialty1_PrimaryID, Specialty2_PrimaryID, Specialty3_PrimaryID, etc). I am trying to export the data out of the old database and separate these into these separate columns. I know I can use indexof and substring to do this - I just need help with the syntax.
So this query:
Select swvar_specialties as Specialty1_PrimaryID
From PhysDirectory
might return results similar to 39,52,16. I need this query to display Specialty1_PrimaryID = 39, Specialty2_PrimaryID = 52, and Specialty3_PrimaryID = 16 in the results. Below is my query so far. I will eventually have a join to pull the specialty names from the specialties table. I just need to get this worked out first.
Select pd.ref as PrimaryID, pd.swvar_name_first as FirstName, pd.swvar_name_middle as MiddleName,
pd.swvar_name_last as LastName, pd.swvar_name_suffix + ' ' + pd.swvar_name_degree as NameSuffix,
pd.swvar_birthdate as DateOfBirth,pd.swvar_notes as AdditionalInformation, 'images/' + '' + pd.swvar_photo as ImageURL,
pd.swvar_philosophy as PhilosophyOfCare, pd.swvar_gender as Gender, pd.swvar_specialties as Specialty1_PrimaryID, pd.swvar_languages as Language1_Name
From PhysDirectory as pd
The article Split function equivalent in T-SQL? provides some details on how to use a split function to split a comma-delimited string.
By modifying the table-valued function in presented in this article to provide an identity column we can target a specific row such as Specialty1_PrimaryID:
/*
Splits string into parts delimitered with specified character.
*/
CREATE FUNCTION [dbo].[SDF_SplitString]
(
#sString nvarchar(2048),
#cDelimiter nchar(1)
)
RETURNS #tParts TABLE (id bigint IDENTITY, part nvarchar(2048) )
AS
BEGIN
if #sString is null return
declare #iStart int,
#iPos int
if substring( #sString, 1, 1 ) = #cDelimiter
begin
set #iStart = 2
insert into #tParts
values( null )
end
else
set #iStart = 1
while 1=1
begin
set #iPos = charindex( #cDelimiter, #sString, #iStart )
if #iPos = 0
set #iPos = len( #sString )+1
if #iPos - #iStart > 0
insert into #tParts
values ( substring( #sString, #iStart, #iPos-#iStart ))
else
insert into #tParts
values( null )
set #iStart = #iPos+1
if #iStart > len( #sString )
break
end
RETURN
END
Your query can the utilise this split function as follows:
Select
pd.ref as PrimaryID,
pd.swvar_name_first as FirstName,
pd.swvar_name_middle as MiddleName,
pd.swvar_name_last as LastName,
pd.swvar_name_suffix + ' ' + pd.swvar_name_degree as LastName,
pd.swvar_birthdate as DateOfBirth,pd.swvar_notes as AdditionalInformation,
'images/' + '' + pd.swvar_photo as ImageURL,
pd.swvar_philosophy as PhilosophyOfCare, pd.swvar_gender as Gender,
(Select part from SDF_SplitString(pd.swvar_specialties, ',') where id=1) as Specialty1_PrimaryID,
(Select part from SDF_SplitString(pd.swvar_specialties, ',') where id=2) as Specialty2_PrimaryID,
pd.swvar_languages as Language1_Name
From PhysDirectory as pd

TSQL - CONCAT_NULL_YIELDS_NULL ON Not Returning Null?

I have had a look around and seem to have come across a strange issue with SQL Server 2008 R2.
I understand that with CONCAT_NULL_YIELDS_NULL = ON means that the following will always resolve to NULL
SELECT NULL + 'My String'
I'm happy with that, however when using this in conjunction with COALESCE() it doesn’t appear to be working on my database.
Consider the following query where MyString is VARCHAR(2000)
SELECT COALESCE(MyString + ', ', '') FROM MyTableOfValues
Now in my query, when MyString IS NULL it returns an empty (NOT NULL) string. I can see this in the query results window.
However unusually enough, when running this in conjunction with an INSERT it fails to recognise the CONCAT_NULL_YIELDS_NULL instead, inserting a blank ‘, ‘.
Query is as follows for insert.
CONCAT_NULL_YIELDS_NULL ON
INSERT INTO Mytable(StringValue)
SELECT COALESCE(MyString + ', ', '')
FROM MyTableOfValues
Further to this I have also checked the database and CONCAT_NULL_YIELDS_NULL = TRUE…
Use NULLIF(MyString, '') instead of just MyString:
SELECT COALESCE(NULLIF(MyString, '') + ', ', '') FROM MyTableOfValues
Coalesce returns the first nonnull expression among its arguments.
You're getting a ', ' because it's the first nonnull expression in your coalesce call.
http://msdn.microsoft.com/en-us/library/ms190349.aspx
From some of the answers provided I was able to assertain a more in depth understanding of COALESCE().
The reason the above query did not fully work was because although I was checking for nulls, and empty string ('') is not considered null. Therefore although the above query worked, I should have checked for empty strings in my table first.
e.g.
SELECT COALESCE(FirstName + ', ', '') + Surname
FROM
(
SELECT 'Joe' AS Firstname, 'Bloggs' AS Surname UNION ALL
SELECT NULL, 'Jones' UNION ALL
SELECT '', 'Jones' UNION ALL
SELECT 'Bob', 'Tielly'
) AS [MyTable]
Will return
FullName
-----------
Joe, Bloggs
Jones
, Jones
Bob, Tielly
Now row 3 has returned a "," character which I was not originally expecting due to a Blank but NOT NULL value.
The following code now works as expected as it checks for blank values. It works, but it looks like I took the long way around. There may be a better way.
-- Ammended Query
SELECT COALESCE(REPLACE(FirstName, Firstname , Firstname + ', '), '') + Surname AS FullName0
FROM
(
SELECT 'Joe' AS Firstname, 'Bloggs' AS Surname UNION ALL
SELECT NULL, 'Jones' UNION ALL
SELECT '', 'Jones' UNION ALL
SELECT 'Bob', 'Tielly'
) AS [MyTable]

DESCENDING/ASCENDING Parameter to a stored procedure

I have the following SP
CREATE PROCEDURE GetAllHouses
set #webRegionID = 2
set #sortBy = 'case_no'
set #sortDirection = 'ASC'
AS
BEGIN
Select
tbl_houses.*
from tbl_houses
where
postal in (select zipcode from crm_zipcodes where web_region_id = #webRegionID)
ORDER BY
CASE UPPER(#sortBy)
when 'CASE_NO' then case_no
when 'AREA' then area
when 'FURNISHED' then furnished
when 'TYPE' then [type]
when 'SQUAREFEETS' then squarefeets
when 'BEDROOMS' then bedrooms
when 'LIVINGROOMS' then livingrooms
when 'BATHROOMS' then bathrooms
when 'LEASE_FROM' then lease_from
when 'RENT' then rent
else case_no
END
END
GO
Now everything in that SP works but I want to be able to choose whether I want to sort ASCENDING or DESCENDING.
I really can't fint no solution for that using SQL and can't find anything in google.
As you can see I have the parameter sortDirection and I have tried using it in multiple ways but always with errors... Tried Case Statements, IF statements and so on but it is complicated by the fact that I want to insert a keyword.
Help will be very much appriciated, I have tried must of the things that comes into mind but haven't been able to get it right.
You could use two order by fields:
CASE #sortDir WHEN 'ASC' THEN
CASE UPPER(#sortBy)
...
END
END ASC,
CASE #sortDir WHEN 'DESC' THEN
CASE UPPER(#sortBy)
...
END
END DESC
A CASE will evaluate as NULL if none of the WHEN clauses match, so that causes one of the two fields to evaluate to NULL for every row (not affecting the sort order) and the other has the appropriate direction.
One drawback, though, is that you'd need to duplicate your #sortBy CASE statement. You could achieve the same thing using dynamic SQL with sp_executesql and writing a 'ASC' or 'DESC' literal depending on the parameter.
That code is going to get very unmanageable very quickly as you'll need to double nest your CASE WHEN's... one set for the Column to order by, and nested set for whethers it's ASC or DESC
Might be better to consider using Dynamic SQL here...
DECLARE #sql nvarchar(max)
SET #sql = '
Select
tbl_houses.*
from tbl_houses
where
postal in (select zipcode from crm_zipcodes where web_region_id = ' + #webRegionID + ') ORDER BY '
SET #sql = #sql + ' ' + #sortBy + ' ' + #sortDirection
EXEC (#sql)
You could do it with some dynamic SQL and calling it with an EXEC. Beware SQL injection though if the user has any control over the parameters.
CREATE PROCEDURE GetAllHouses
set #webRegionID = 2
set #sortBy = 'case_no'
set #sortDirection = 'ASC'
AS
BEGIN
DECLARE #dynamicSQL NVARCHAR(MAX)
SET #dynamicSQL =
'
SELECT
tbl_houses.*
FROM
tbl_houses
WHERE
postal
IN
(
SELECT
zipcode
FROM
crm_zipcodes
WHERE
web_region_id = ' + CONVERT(nvarchar(10), #webRegionID) + '
)
ORDER BY
' + #sortBy + ' ' + #sortDirection
EXEC(#dynamicSQL)
END
GO