ORDER BY name without leading "the" (and other complex code) - sql

I'm sorting song names from a SQLite database, and I'd like to sort ignoring any leading "The ". So, for example:
1 Labradors are Lovely
2 The Last Starfighter
3 Last Stop before Heaven
This answer solves this need in the simple case:
SELECT name FROM songs
ORDER BY
CASE WHEN instr(lower(name),'the ')=1 THEN substr(name,5)
ELSE name
END
COLLATE NOCASE;
However, I'm already using a complex transformation on the name column. Combining the two I get this ugly, non-DRY code:
SELECT n, name
FROM songs
ORDER BY
CASE WHEN name GLOB '[0-9]*' THEN 1
ELSE 0
END,
CASE WHEN name GLOB '[0-9]*' THEN CAST(name AS INT)
ELSE CASE WHEN instr(lower(name),'the ')=1 THEN
replace(
replace(
replace(
replace(
substr(name,5),
'.',''
),
'(',''
),
'''',''
),
' ',' '
)
ELSE
replace(
replace(
replace(
replace(name,'.',''),
'(',''
),
'''',''
),
' ',' '
)
END
END
COLLATE NOCASE;
Is there a way to use a variable or something during the query so that I can DRY up the code, and only have all that punctuation-replacement taking place in one location instead of two different case branches?

Something like this should work.
SELECT n, name FROM (
SELECT n, name,
CASE WHEN instr(lower(name),'the ')=1 THEN substr(name,5)
ELSE name
END AS NameWithoutThe
FROM songs
) AS inr
ORDER BY
CASE WHEN name GLOB '[0-9]*' THEN 1
ELSE 0
END,
CASE WHEN name GLOB '[0-9]*' THEN CAST(NameWithoutThe AS INT)
ELSE
replace(
replace(
replace(
replace(
NameWithoutThe,
'.',''
),
'(',''
),
'''',''
),
' ',' '
)
END
COLLATE NOCASE;

Related

LIKE statement to compare strings with hyphen

I am working in SQL and I have 3 columns Current Name, Given Full Name and Whether the names match (Y or No)
The problem with that is that when I am comparing the strings in the first 2 columns, it is not showing me the current result. For example, I am not finding a way to prove that 'Tushar Sharma' is same as 'Tushar-Sharma' considering that Tushar Sharma is the current full name and Tushar-Sharma is the name that has been extracted from a report.
I am stuck at the LIKE statement as to what to do if I want to have hyphen(-) included in the comparison so that I get a Y in the 3rd column.
Thank you
One option is to remove the hyphen for the comparison:
select (case when replace(given_name, '-', '') = replace(full_name, '-', '') then 'Y' else 'N' end) as names_match
You can use replace() with like as well:
select (case when replace(given_name, '-', '') like '%' + replace(full_name, '-', '') '%' then 'Y' else 'N' end) as names_match
Replace - with whitespace and compare, you can also use regex or fuzzy matching to improve the match for other conditions.
AND REPLACE(CurrentName, '-', ' ') = REPLACE(GivenName, '-', ' ');
Ex:
AND REPLACE('Tushar Sharma', '-', ' ') = REPLACE('Tushar-Sharma', '-', ' ')
will eval to
AND 'Tushar Sharma' = 'Tushar Sharma'
this will work:
select currentname,givenfullname,case when regexp_replace(currentname,' ','') like
regexp_replace(givenfullname,' ','') the 'Y' else 'N' end as matchstatus from
table_name;

Parsing Name Field in SQL

I am trying to separate a name field into the appropriate fields. The name field is not consistently the same. It can show up as Doe III,John w or Doe,John, or Doe III,John, or Doe,John W or it may be lacking the suffix and or middle initial. Any ideas would be greatly appreciated.
SELECT (
CASE LEN(REPLACE(FirstName, ' ', ''))
WHEN LEN(FirstName + ' ') - 1
THEN PARSENAME(REPLACE(FirstName, ' ', '.'), 2)
ELSE PARSENAME(REPLACE(FirstName, ' ', '.'), 3)
END
) AS LastName
,(
CASE LEN(REPLACE(FirstName, ' ', ''))
WHEN LEN(FirstName + ',') - 1
THEN NULL
ELSE PARSENAME(REPLACE(FirstName, ' ', '.'), 2)
END
) AS Suffix
,PARSENAME(REPLACE(FirstName, ' ', '.'), 1) AS FirstName
FROM Trusts.dbo.tblMember
I need the name regardless of the format, as stated above, to parse into the appropriate fields of LastName,Suffix,FirstName,MiddleInitial, regardless of whether it has a suffix or a middle initial
If the given 4 names are the only type of cases, then you can use something like below.
Note: I used a CTE table tbl2 to separate comma_pos,first_space,second_space for better understanding in the main query. You can replace these value in main query with their corresponding function in CTE, to make the main query faster. I mean replace comma_pos in main query with charindex(',',name) an so on.
Also I am assuming that there are no leading/trailing or extra whitespaces or any junk character in name column. If you have, then sanitize your data first before proceeding.
Rexter Sample
with tbl2 as (
select tbl.*,
charindex(',',name) as comma_pos,
charindex(' ',name,1) first_space,
charindex(' ',name,charindex(' ',name,1)+1) second_space
from tbl)
select tbl2.name
,case when second_space <> 0
then substring(name,comma_pos+1,second_space-comma_pos-1)
when first_space > comma_pos
then substring(name,comma_pos+1,first_space-comma_pos-1)
else substring(name,comma_pos+1,len(name)-comma_pos)
end as first_name
,case when second_space <> 0
then substring(name,second_space+1,len(name)-second_space)
when first_space > comma_pos
then substring(name,first_space+1,len(name)-first_space)
end as middle_name
,case when first_space=0 or first_space>comma_pos
then substring(name,1,comma_pos-1)
else substring(name,1,first_space-1)
end as last_name
,case when first_space=0 or first_space>comma_pos
then null
else substring(name,first_space,comma_pos-first_space)
end as suffix
from tbl2;

SQL how to replace string which contains only new lines?

My situation is that in some cases my field contain several (multiple) new lines and nothing else.
I can't use this:
SELECT REPLACE(REPLACE(fielddata, CHAR(13), ''), CHAR(10), '')
because I also have a normal ones, and as I understand this will replace all new lines.
As I understand, I need somehow check if string contains only new lines, and if it does, replace them with ''.
How can I accomplish that?
One way to solve it is to use case, len, and trim to figure out if the column have data in that specific row:
SELECT CASE WHEN LEN(
LTRIM(
RTRIM(
REPLACE(
REPLACE(
fielddata, CHAR(13), ''
), CHAR(10), ''
)
)
)
) = 0 THEN
''
ELSE
fielddata
END as fielddata
You can use a CASE expression like
CASE WHEN REPLACE(my_string_column, CHAR(13), '') = ''
THEN REPLACE(REPLACE(fielddata, CHAR(13), ''), CHAR(10), '')
ELSE my_string_column END AS Computed_Column

Remove dot(.) from amout value using sqlite query

I want to remove dots (.) before decimal places in my amount value. Below is my database table
Query
SELECT sum( REPLACE( REPLACE( amt, ',', '' ) , ' ', '' ) ) FROM amt_demo
when I run the above query I get the following output.
Output
But I want the total sum of the values like:
1333.00
100000.50
100000.00
123456789
123456789
123456789
---------------
370571700.50
Any idea how can I solve this?
Use Maths CEIL function
SELECT CEIL(sum( REPLACE( REPLACE( amt, ',', '' ) , ' ', '' ) ))

How to combine SQL queries for same column?

I have searched but not found any examples for my particular problem.
I am trying to strip some unwanted text from a column containing department names. I am trying to combine 2 queries to do this.
This first query strips all characters after the colon in the name:
SELECT
CASE WHEN CHARINDEX(':', DB.Table.DEPT)>0
THEN
LEFT(DB.Table.DEPT, CHARINDEX(':', DB.Table.DEPT)-1)
ELSE
DB.Table.DEPT
END
FROM
DB.Table
The second query strips the prefix from the name:
SELECT
REPLACE(
REPLACE(
REPLACE (DB.Table.DEPT,'[NA1] ','')
,'[NA2] ', '')
,'[NA3] ', '')
FROM
DB.Table
Both of these work great independent of each other, but when I try to combine them it fails.
SELECT
CASE WHEN CHARINDEX(':', DB.Table.DEPT)>0
THEN
LEFT(DB.Table.DEPT, CHARINDEX(':', DB.Table.DEPT)-1)
ELSE
DB.Table.DEPT
END
FROM
(SELECT
REPLACE(
REPLACE(
REPLACE (DB.Table.DEPT,'[NA1] ','')
,'[NA2] ', '')
,'[NA3] ', '')
FROM
DB.Table)
I could really use some guidance with this.
Thanks in advance.
Your query is syntactically incorrect, because you need an alias for the subquery and for the expression result:
SELECT (CASE WHEN CHARINDEX(':', DEPT)>0
THEN LEFT(DEPT, CHARINDEX(':', DEPT)-1)
ELSE DEPT
END)
FROM (SELECT REPLACE(REPLACE(REPLACE(t.DEPT,'[NA1] ',''
), '[NA2] ', ''
), '[NA3] ', ''
) as DEPT
FROM DB.Table t
) t;
EDIT:
To see both the original and new department:
SELECT (CASE WHEN CHARINDEX(':', new_DEPT) > 0
THEN LEFT(new_DEPT, CHARINDEX(':', newj_DEPT)-1)
ELSE new_DEPT
END),
Orig_DEPT
FROM (SELECT REPLACE(REPLACE(REPLACE(t.DEPT,'[NA1] ',''
), '[NA2] ', ''
), '[NA3] ', ''
) as new_DEPT,
t.DEPT as orig_DEPT
FROM DB.Table t
) t
You should always name your subquerys.
Try this:
SELECT
CASE WHEN CHARINDEX(':', x.DEPT)>0
THEN
LEFT(x.DEPT, CHARINDEX(':', x.DEPT)-1)
ELSE
x.DEPT
END AS DEPT
FROM
(
SELECT
REPLACE(REPLACE(REPLACE (DEPT,'[NA1] ','') ,'[NA2] ', ''),'[NA3] ', '') AS DEPT
FROM
DB.Table
) x