SQL Server : passing company id (int) with comma in where condition [duplicate] - sql

This question already has answers here:
How to split a comma-separated value to columns
(38 answers)
Closed 4 years ago.
I am working in SQL Server 2008. I am facing a problem in a where condition, passing multiple company ID values separated by comma (,) to use in Int company ID.
ALTER Procedure
[dbo].[SP_WorkOrderDetails] #CompanyID varchar(50)
as begin
Select
*
from
ClientContract C
left join
WorkOrder W
on
C.Id=W.ClientContractId
left join
ClientContractContacts CB
on
CB.ClientContractld=C.Id
left join
Client CL
on
CL.Id= C.Clientld
left join
Client CN
on
CN.Id= CB.Contactld
left join
BaseUnit B
on
B.Id=W.BaseUnitId
left join
users u
on
u.Staffld = W.AssignedTo
left join
LatticeERP_DFS..sv_App_Staff SPT
on
SPT.Leaderld=W.AssignedTo and
SPT.Module = 'S'
left join
Staff SS
on
SS.Id=u.StaffId --and ss.IsTeamLeader = 1
left join
Companies Comp
on
Comp.id=C.Companyld
Where
convert(nvarchar(50),isnull(C.companyID, 1)) in (replace('1,7', '''', ','))
Order By
ContractCode,
WorkOrderNo Desc
end

can you try this
IN (select cast ( STRING_SPLIT ( '1,7' , ',' ) as int ) )
or may be this
IN ( SELECT
Split.a.value('.', 'VARCHAR(100)') AS CVS
FROM
(
SELECT CAST ('<M>' + REPLACE('1,7', ',', '</M><M>') + '</M>' AS XML) AS CVS
) AS A CROSS APPLY CVS.nodes ('/M') AS Split(a) )

you can use this table-valued function:
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
create FUNCTION dbo.SplitString(#str VARCHAR(4000),#seprator VARCHAR(1))
RETURNS TABLE
AS
RETURN ( WITH tokens(p,a,b) AS (SELECT 1,1,CHARINDEX(#seprator,#str)
UNION ALL SELECT p+1,b+1,CHARINDEX(#seprator,#str,b+1)
FROM tokens WHERE b>0
)
SELECT
SUBSTRING(#str,a,CASE WHEN b > 0 THEN b-a ELSE 4000 end)
AS VALUE
FROM tokens)
GO
use it like:
... where ID In(select value from dbo.SplitString('1,7,...',','))

Related

How to convert this query for Spark SQL

I'm trying to convert an SQL Server query to execute it into a Notebook, but I can't figure out how to convert a "CROSS APPLY" into something that Spark can understand.
Here is my SQL Server query :
WITH Benef as (
SELECT DISTINCT
IdBeneficiaireSource
,Adress
FROM
UPExpBeneficiaryStaging
)
-------- Split Adress --------
,AdresseBenefTemp1 as (
SELECT
IdBeneficiaireSource
,REPLACE(REPLACE(Adress, char(10), '|'), char(13), '|') as AdresseV2
FROM
Benef
)
,AdresseBenefTemp2 as (
SELECT
IdBeneficiaireSource
,value as Adresse
,ROW_NUMBER() OVER(PARTITION BY IdBeneficiaireSource ORDER BY (SELECT NULL)) as LigneAdresse
FROM
AdresseBenefTemp1
CROSS APPLY string_split(AdresseV2, '|')
)
,AdresseBenefFinal as (
SELECT DISTINCT
a.IdBeneficiaireSource
,b.Adresse as Adresse_1
,c.Adresse as Adresse_2
,d.Adresse as Adresse_3
FROM
AdresseBenefTemp2 as a
LEFT JOIN AdresseBenefTemp2 as b on b.IdBeneficiaireSource = a.IdBeneficiaireSource AND b.LigneAdresse = 1
LEFT JOIN AdresseBenefTemp2 as c on c.IdBeneficiaireSource = a.IdBeneficiaireSource AND c.LigneAdresse = 2
LEFT JOIN AdresseBenefTemp2 as d on d.IdBeneficiaireSource = a.IdBeneficiaireSource AND d.LigneAdresse = 3
)
-------------------------------
SELECT
a.IdBeneficiaireSource
,Adresse_1
,Adresse_2
,Adresse_3
FROM
AdresseBenefFinal
(This query split an address field into three address fields)
When I run it into a Notebook, it says that "CROSS APPLY" is not correct.
Thanks.
Correct me if I'm wrong, but the cross apply string_split is basically a cross join for each entry in the resulting split.
In Spark you're able to use an explode for this (https://docs.databricks.com/sql/language-manual/functions/explode.html). So you should be able to add another CTE in between where you explode the splitted (https://docs.databricks.com/sql/language-manual/functions/split.html) results from AddresseV2 by '|'.

Where Complex Results and NULLS - SQL C#

I have a query in the database with a textbox that brings me from another field if there is a record but I want it to bring me a null when it does not exist in the base
SELECT [restaurantes]
,[ubicacion]
FROM [col].[dbo].[bog]
where restaurantes in ('colombia','bogota')
and result is this :
restaurantes - ubicacion
colombia - norte_espa
and not get bogota because not have register in database i need restaurant and ubicacion i need show null
result :
restaurantes - ubicacion
colombia - norte_espa
bogota - Null or Not exists that register
its possible ?
You can use a VALUES clause as the driving row, along with a LEFT JOIN
SELECT v.[restaurantes]
,b.[ubicacion]
FROM (VALUES
('colombia'),
('bogota')
) v(restaurantes)
LEFT JOIN [col].[dbo].[bog] b ON b.restaurantes = v.restaurantes;
For very old versions of SQL Server which do not support VALUES you can use UNION ALL in a subquery
SELECT v.[restaurantes]
,b.[ubicacion]
FROM (
SELECT 'colombia' AS restaurantes
UNION ALL
SELECT 'bogota'
) v
LEFT JOIN [col].[dbo].[bog] b ON b.restaurantes = v.restaurantes;
Perhaps string_split() in concert with a Left Join
Example
Select restaurantes = a.value
,B.[ubicacion]
From string_split('colombia,bogota',',') A
Left Join [col].[dbo].[bog] B
on A.value = B.restaurantes
Update Lower Version of SQL Server
Declare #List varchar(max) = 'colombia,bogota'
Select restaurantes = a.RetVal
,B.[ubicacion]
From (
Select RetSeq = row_number() over (order by 1/0)
,RetVal = ltrim(rtrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>' + replace((Select replace(#List,',','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) A
Left Join [col].[dbo].[bog] B
on A.RetVal = B.restaurantes

trying to concatenate a column into a comma delimited list

i have 3 tables, 1 for products and one for categories the products are assigned to. what IM trying to do is concatenate the column called stCategoryName to a single column in a comma delimited list.
Basically I have the products table containing the primary key for each product and im trying to figure out how to concatenate all the stcategoryName column next to each product so i can have a simplified return
what im trying to get is the following.
stProductID stCategoryName
123 category1,category2,category3
SELECT
dbo.StoreItemTracking.StCategoryID,
dbo.StoreItemTracking.StProductID,
dbo.StoreItemTracking.viewOrder,
dbo.StoreCategories.StCategoryName,
dbo.Store_Products.PartNumber
FROM
dbo.StoreItemTracking
INNER JOIN dbo.StoreCategories
ON dbo.StoreItemTracking.StCategoryID = dbo.StoreCategories.StCategoryID
INNER JOIN dbo.Store_Products
ON dbo.StoreItemTracking.StProductID = dbo.Store_Products.ID
Im stuck as to how to concatenate a column where the query contains 3 tables to select from.
any help greatly appreciated
Look at using coalesce to turn category into a CSV:
See example:
DECLARE #EmployeeList varchar(100)
SELECT #EmployeeList = COALESCE(#EmployeeList + ', ', '')
+ CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1
SELECT #EmployeeList
You can also use CTE's or Subqueries. See:
http://archive.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=createacommadelimitedlist
Another nice and easy example:
http://www.codeproject.com/Articles/21082/Concatenate-Field-Values-in-One-String-Using-CTE-i
This:
FId FName
--- ----
2 A
4 B
5 C
6 D
8 E
with:
;WITH ABC (FId, FName) AS
(
SELECT 1, CAST('' AS VARCHAR(8000))
UNION ALL
SELECT B.FId + 1, B.FName + A.FName + ', '
FROM (And the above query will return
SELECT Row_Number() OVER (ORDER BY FId) AS RN, FName FROM tblTest) A
INNER JOIN ABC B ON A.RN = B.FId
)
SELECT TOP 1 FName FROM ABC ORDER BY FId DESC
becomes:
FName
----------------------------
A, B, C, D, E,
Don't understand how your products and categories are connected but in general I do like this to create comma separated lists.
SELECT table1.Id
,Csv
FROM table1
CROSS APPLY (
-- Double select so we can have an alias for the csv column
SELECT (SELECT ',' + table2.Name
FROM table2
WHERE table2.Id = table1.Id
FOR XML PATH('')
) AS RawCsv
) AS CA1
CROSS APPLY (
-- Trim the first comma
SELECT RIGHT(RawCsv, LEN(RawCsv) - 1) AS Csv
) AS CA2

Grouping the results of multiple rows in one column [duplicate]

This question already has answers here:
Can I Comma Delimit Multiple Rows Into One Column? [duplicate]
(5 answers)
Closed 10 years ago.
The query below gives me two results where everything is same except the last column v2_roles.id. Is there a way to group them in one column (may be a comma seprated list) and get just one result back
SELECT v2_admin.adminid,
v2_admin.adminname,
v2_admin.login,
v2_admin.email,
v2_roles.id
FROM v2_admin
INNER JOIN v2_admin_roles
ON v2_admin.adminid = v2_admin_roles.adminid
INNER JOIN v2_roles
ON v2_admin_roles.roleid = v2_roles.id
WHERE v2_admin.adminid = 2
This should also work,
;WITH mytable AS (
SELECT v2_admin.adminid,
v2_admin.adminname,
v2_admin.login,
v2_admin.email,
v2_roles.id
FROM v2_admin
INNER JOIN v2_admin_roles
ON v2_admin.adminid = v2_admin_roles.adminid
INNER JOIN v2_roles
ON v2_admin_roles.roleid = v2_roles.id
WHERE v2_admin.adminid = 2
)
SELECT t1.adminid,t1.adminname, t1.login, t1.email,
roleIds =REPLACE( (SELECT convert(varchar,id) AS [data()]
FROM mytable t2
WHERE t2.adminid = t1.adminid
--ORDER BY t2.adminid
FOR XML PATH('')
), ' ', ' , ')
FROM mytable t1
GROUP BY t1.adminid,t1.adminname, t1.login, t1.email ;
This is a little trick using FOR XML to convert the field to a list and STUFF to remove the beginning comma -- this should be close (untested):
SELECT v2_admin.adminid,
v2_admin.adminname,
v2_admin.login,
v2_admin.email,
STUFF(
(
SELECT ',' + CAST(v2_roles.id as varchar) AS [text()]
FROM v2_roles
WHERE v2_admin_roles.roleid = v2_roles.id
ORDER BY v2_roles.id
FOR XML PATH('')
), 1, 1, '') AS Roles
FROM v2_admin
INNER JOIN v2_admin_roles
ON v2_admin.adminid = v2_admin_roles.adminid
WHERE v2_admin.adminid = 2
GROUP BY v2_admin.adminid,
v2_admin.adminname,
v2_admin.login,
v2_admin.email

How to check intersection of subqueries in query?

I have the next query:
SELECT c.client_code, a.account_num, m.account_close_date, u.uso, m.product_name
FROM accounts a INNER JOIN Clients c ON c.id = a.client_id INNER JOIN
Uso u ON c.uso_id = u.uso_id INNER JOIN Magazine m ON a.account_id = m.account_id
and I need to compare product_name with input parameter.
product_name and input parameter #s are comma-delimited strings.
I use next split function:
ALTER FUNCTION [dbo].[Split]
(
#s VARCHAR(max),
#split CHAR(1)
)
RETURNS #temptable TABLE (items VARCHAR(MAX))
AS
BEGIN
DECLARE #x XML
SELECT #x = CONVERT(xml,'<root><s>' + REPLACE(#s,#split,'</s><s>') + '</s></root>');
INSERT INTO #temptable
SELECT [Value] = T.c.value('.','varchar(20)')
FROM #X.nodes('/root/s') T(c);
RETURN
END;
I think that I need to check the intersection of tables, which I will receive after split of product_name and after split of input parameter. I trid to do this:
WHERE (select * from dbo.Split(m.product_name, ';')
INTERSECT select * from dbo.Split('product1;product2',';'))
is not null
But it does not work quite right. Please, help me.
INTERSECT requires the same column output and is used like UNION or EXCEPT: not in the WHERE clause
Just JOIN onto the udf
...
INNER JOIN
Magazine m ON a.account_id = m.account_id
INNER JOIN
dbo.Split(#parameter, ';') CSV ON m.productname = CSV.items
If you need to split m.productname, if you can't fix the design, use CROSS APPLY
...
INNER JOIN
Magazine m ON a.account_id = m.account_id
CROSS APPLY
dbo.Split(m.productname, ';') WTF
INNER JOIN
dbo.Split(#parameter, ';') CSV ON WTF.items = CSV.items
However, JOIN and INTERSECT give different results if #parameter has duplicated values. Add a DISTINCT to the UDF for example to get around this. Or change the udf JOIN into EXISTS