I want to select the value before and after the comma - sql

Sql Query for select the value before and after the comma
There is a table called employee, there is 3 fields..Id,Name,Departmentid
In DepartmentId it consist of 3 id 201,301,401.
From this want to execute
Select * from employee where DepartmentId =301

This will work if you're always looking to match on the number in the middle, e.g. 301 in your example.
SELECT *
FROM employee
WHERE
SUBSTRING (
DepartmentId,
CHARINDEX(',', DepartmentId, 0) + 1,
CHARINDEX(',', DepartmentId, CHARINDEX(',', DepartmentId, 0) + 1) - CHARINDEX(',', DepartmentId, 0) - 1
) = '301'
If 301 can be in any location in that field then you can just use LIKE
SELECT *
FROM employee
WHERE DepartmentId LIKE '%301%'

SELECT * FROM EMPLOYEE WHERE DEPARTMENTID LIKE '%301%'
Even if it works, I don't really understand how your DB is designed and why you need commas

You can use parsename() function:
. . .
where parsename(replace(DepartmentId, ',', '.'), 2) = 301;
However like predicate also useful:
. . .
where DepartmentId LIKE '%301%';

Comma seperated columns are an antipattern. You want to normalize your departments.
However, here's one way to do it:
select * from employee
where '301' in (SELECT value FROM STRING_SPLIT(department, ','))

If you have departments like 1301 or 3011 then a simple LIKE might fail
Please check following SQL code
select * from employees where ','+departmentid+',' like '%,301,%'
And other option is to split departmentid column into each seperate department id value list
If you have a SQL Server before SQL Server 2016 then you need your own custome SQL string split function.
Then you can use following SQL query
select e.*
from employees as e
cross apply dbo.split(departmentid,',') as s
where s.val = '301'
If you are working on SQL Server 2016 or SQL Server 2017, string_split build-in SQL function can be used as follows again in a CROSS APPLY query
SELECT e.*
FROM employees as e
CROSS APPLY STRING_SPLIT(departmentid, ',')
WHERE value = '301'
One last method can be using SQL XML query by modifying the comma seperated list into an XML data as follows
select
Id, Name, sqlXML.value('.','varchar(5)') as DepId
from (
SELECT
Id, Name,
convert(xml, '<root><t>' + REPLACE(Departmentid, ',', '</t><t>') + '</t></root>') as dlist
FROM employees
) tbl
CROSS APPLY dlist.nodes('/root/t') as XMLData(sqlXML)
WHERE sqlXML.value('.','varchar(5)') = '301'

Related

How does Partitioning By a Substring in T-SQL Work?

I found the perfect example while browsing through sites of what I'm looking for. In this code example, all country names that appear in long formatted rows are concatenated together into one result, with a comma and space between each country.
Select CountryName from Application.Countries;
Select SUBSTRING(
(
SELECT ',' + CountryName AS 'data()'
FROM Application.Countries FOR XML PATH('')
), 2 , 9999) As Countries
Source: https://www.mytecbits.com/microsoft/sql-server/concatenate-multiple-rows-into-single-string
My question is: how can you partition these results with a second column that would read as "Continent" in such a way that each country would appear within its respective continent? The theoretical "OVER (PARTITION BY Continent)" in this example would not work without an aggregate function before it. Perhaps there is a better way to accomplish this? Thanks.
Use a continents table (you seem not to have one, so derive one with distinct), and then use the same code in a cross apply using the where as a "join" condition:
select *
from
(
select distinct continent from Application.Countries
) t1
cross apply
(
Select SUBSTRING(
(
SELECT ',' + CountryName AS 'data()'
FROM Application.Countries as c FOR XML PATH('')
where c.continent=t1.continent
), 2 , 9999) As Countries
) t2
Note that it is more usual, and arguably has more finesse, to use stuff(x,1,1,'')instead of substring(x,2,9999) to remove the first comma.

SQL merge filed with duplicates Data

I have a table with some duplicates Data, I want to merge the job and unit field in one field.
My data currently looks like this:
name job1 Unit1_Level1 Unit1__Level2
-------------------------------------------------------
A Teacher Infomation Information_office
A Staff Secretary Secretary_office
A Staff Engineer Engineer_office
B Teacher Finacial Finacial_office
C Teacher Engineer Engineer_office
C Staff Library Library_office
D Staff Library Library_office
And I want it to look like this:
name job
----------------------------------------------------------------------------------------------------------------
A Teacher-Infomation-Information_office:Staff-Secretary-Secretary_office:Staff-Engineer-Engineer_office
B Teacher-Finacial-Finacial_office
C Teacher-Engineer-Engineer_office:Staff-Library-Library_office
D Staff-Library-Library_office
I try the FOR XML PATH , but still have the duplicate row.
Please help me about the question, thank you.
In TSQL you could use STRING_AGG()
select STRING_AGG(concat(job1,'-', Unit1_level1, '-', Unit1_level2, ':'))
from your_table
Try this combination STRING_AGG an CONCAT_WS
SELECT name, STRING_AGG(a.ct, ':' )
FROM (
SELECT name, CONCAT_WS('-', job1, Unit1_level1, Unit1__Level2, ':') ct
FROM MyTable
) a
GROUP BY name
You could use STRING_AGG() and CONCAT_WS() as the following:
SELECT Name,
STRING_AGG(CONCAT_WS('-', job1, Unit1_Level1, Unit1__Level2), ':')
FROM YourTable
GROUP BY Name;
String_Agg requires an separator value
select STRING_AGG(concat(job1,'-', Unit1_Level1, '-', Unit1_Level2, ':'),' ') a from #tmp

Google BigQuery: iterate CONTAINS function over subquery

Lets assume I have two tables:
girls prefixes
------ ----------
Le-na -na
Lo-ve -ve
Li-na -la
Lu-na -ta
Len-ka -ya
All girls names and prefixes are different length!
I want to select all girl names that contains prefixes table and to do it in a query(imagine I have many names and many prefixes).
I untested that for single case it is being completed like this:
SELECT girls,SOME(girls CONTAINS ("-na")) WITHIN RECORD FROM prefixes
But how do I implement iteration of CONTAINS function over subquery?
e.g.
SELECT girls,SOME(girls CONTAINS (SELECT * FROM prefixes))
WITHIN RECORD FROM prefixes
–– this doesn't work, cause Subselect not allowed in SELECT clause
I'd really appreciate any ideas, I've tried to search for this but couldn't find my case.
Have you tried just using join?
select *
from girls g join
prefixes p
on g.girls like concat('%', p.prefix);
This should work using standard SQL.
Assuming that the prefixes (well, suffixes) are always three characters, you can perform an efficient semi-join with the result of SUBSTR:
#standardSQL
WITH Girls AS (
SELECT name
FROM UNNEST(['Le-na', 'Lo-ve', 'Li-na', 'Lu-na', 'Len-ka']) AS name
),
Suffixes AS (
SELECT suffix
FROM UNNEST(['-na', '-ve', '-la', '-ta', '-ya']) AS suffix
)
SELECT
name
FROM Girls
WHERE EXISTS (
SELECT 1 FROM Suffixes WHERE suffix = SUBSTR(name, LENGTH(name) - 2)
);
Or you can use LIKE, but it is equivalent to performing a cross join with a filter, so it probably won't be as fast:
#standardSQL
WITH Girls AS (
SELECT name
FROM UNNEST(['Le-na', 'Lo-ve', 'Li-na', 'Lu-na', 'Len-ka']) AS name
),
Suffixes AS (
SELECT suffix
FROM UNNEST(['-na', '-ve', '-la', '-ta', '-ya']) AS suffix
)
SELECT
name
FROM Girls
WHERE EXISTS (
SELECT 1 FROM Suffixes WHERE name LIKE CONCAT('%', suffix)
);
Edit: another option that enumerates all name suffixes for use in the semi-join:
#standardSQL
WITH Girls AS (
SELECT name
FROM UNNEST(['Le-na', 'Lo-ve-lala', 'Li-na', 'Lu-eya', 'Len-ka']) AS name
),
Suffixes AS (
SELECT suffix
FROM UNNEST(['-na', '-ve', '-lala', '-ta', '-eya']) AS suffix
),
GirlNamePermutations AS (
SELECT name, SUBSTR(name, LENGTH(name) + 1 - len) AS name_suffix
FROM Girls
CROSS JOIN UNNEST(GENERATE_ARRAY(1, (SELECT MAX(LENGTH(suffix)) FROM Suffixes))) AS len
)
SELECT
name
FROM GirlNamePermutations
WHERE EXISTS (
SELECT 1
FROM Suffixes
WHERE suffix = name_suffix
);
If you know the range of suffix lengths, you could hard-code it instead, e.g. replace:
CROSS JOIN UNNEST(GENERATE_ARRAY(1, (SELECT MAX(LENGTH(suffix)) FROM Suffixes))) AS len
with:
CROSS JOIN UNNEST(GENERATE_ARRAY(1, 5)) AS len
Below is for BigQuery Standard SQL
#standardSQL
WITH girls AS (
SELECT name
FROM UNNEST(['Le-na', 'Lo-ve', 'Li-na', 'Lu-na', 'Len-ka']) AS name
),
suffixes AS (
SELECT suffix
FROM UNNEST(['-na', '-ve', '-la', '-ta', '-ya']) AS suffix
)
SELECT name
FROM girls
JOIN suffixes
ON ENDS_WITH(name, suffix)
as an option - in case you will need to extend this to find fragments inside name - you can use REGEXP_CONTAINS
SELECT name
FROM girls
JOIN suffixes
ON REGEXP_CONTAINS(name, suffix)
or - STARTS_WITH to match by prefixes (vs. suffixes)
SELECT name
FROM girls
JOIN suffixes
ON STARTS_WITH(name, suffix)

SQL Server : combine two rows into one

I want to write a query which will display the following result
FROM
ID Contract# Market
1 123kjs 40010
1 123kjs 40011
2 121kjs 40098
2 121kjs 40099
TO
ID Contract# Market
1 123kjs 40010,40011
2 121kjs 40098,40099
Try out this query, I use GROUP_CONCAT to turn column fields into 1 row field.
Also notice that you should rename the FROM clause with the name of your table.
SELECT ID,Contract#, GROUP_CONCAT(Market SEPARATOR ',')
FROM nameOfThatTable GROUP BY ID;
Try this out. I used PIVOT to solve it.
SELECT
ID,
Contract#,
ISNULL(CONVERT(varchar,[40010]) + ',' + CONVERT(varchar,[40011]),
CONVERT(varchar,[40098]) + ',' + CONVERT(varchar,[40099])) AS Market FROM
( SELECT * FROM ContractTable) AS A
PIVOT(MIN(Market) FOR Market IN ([40010],[40011],[40098],[40099])) AS PVT
ORDER BY ID
You can use ', ' + CAST(Market AS VARCHAR(30)) in sub-query and join Id and Contract# of sub-query with outer query to get values of Market as Comma Separated Values for each Id and Contract#.
SELECT DISTINCT ID,Contract#,
SUBSTRING(
(SELECT ', ' + CAST(Market AS VARCHAR(30))
FROM #TEMP T1
WHERE T2.Id=T1.Id AND T2.Contract#=T1.Contract#
FOR XML PATH('')),2,200000) Market
FROM #TEMP T2
Click here to view result
Note
.........
If you want to get CSV values for Id only, remove T2.Contract#=T1.Contract# from sub-query.

How to use Order By clause on a column containing string values separated by comma?

I have a table with a column named Skills which contains comma separated values for different employees like
EmpID Skills
1 C,C++,Oracle
2 Java,JavaScript,PHP
3 C,C++,Oracle
4 JavaScript,C++,ASP
5 C,C++,JavaScript
So I want to write a query which will order all the employees first who knows JavaScript, how can I get this result?
You should not use one attribute to store multiple values. That goes against relation DB principles.
Instead of that you should create additional table to store skills and refer to employee in it. Then, your query will looks like:
SELECT
*
FROM
employees
LEFT JOIN employees_skills
ON employee.id=employees_skills.employee_id
WHERE
employees_skills='JavaScript'
Try this
SELECT *
FROM
(
SELECT *
,CASE WHEN Skills LIKE '%JavaScript%' THEN 0 ELSE 1 END AS Rnk
FROM MyTable
) T
ORDER BY rnk,EmpID
DEMO
OR
SELECT * FROM #MyTable
ORDER BY CASE WHEN Skills LIKE '%JavaScript%' THEN 0 ELSE 1 END,EmpID
select EmpID, Skills
from Table1
order by case when Skills like '%JavaScript%' then 0 else 1 end
Try this:
SELECT *
FROM YourTable
ORDER BY PATINDEX('%JavaScript%', Skills) DESC
But this is a bad way. You should really normalize your table.
For MySQL
select Skills from myTable
order by case Skills
when "Javascript" then 0
when "Java" then 1 when "C++" then 2
end
and so on
For SQL Server
select Skills from myTable
order by case
when Skills="Javascript" then 1
when Skill="Java" then 2
else 3
end
Make sure to start SQL server from 1 (That I'm not sure).
Include an else before end that will show all remaining results.
For more details about SQL Server see this or see this
This works for DB2/400:
with s (id, skill, rest) as
(select id, '', sk from skills
union all
select id, substr(rest, 1, locate(',',rest)-1),
substr(rest,locate(',',rest)+1)
from s
where locate(',',rest) > 0)
select id, skill from s
where skill = 'JavaScript'
order by id