Where Complex Results and NULLS - SQL C# - sql

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

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 '|'.

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

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,...',','))

Existing query optimization

We have 5 tables and we are trying to create a view to get the results.
Below is the view which is working fine.
I need suggestions. Is it a good practice to write this query in this way or it can be optimized in a better way.
SELECT p.Pid, hc.hcid, hc.Accomodation, ghc.ghcid, ghc.ProductFeatures, wp.existing, wp.acute, mc.cardiaccover, mc.cardiaclimitationperiod
FROM TableA p
LEFT JOIN TableB hc
ON p.pid = hc.pid
LEFT JOIN TableC ghc
ON p.pid = ghc.pid
LEFT JOIN (SELECT *
FROM (SELECT hcid,
title,
wperiodvalue + '-' + CASE WHEN
wperiodvalue > 1 THEN
unit +
's' ELSE
unit END wperiod
FROM TableD) d
PIVOT ( Max(wperiod)
FOR title IN (acute,
existing
) ) piv1) wp
ON hc.hcid = wp.hcid
LEFT JOIN (SELECT *
FROM (SELECT hcid,
title + col new_col,
value
FROM TableE
CROSS apply ( VALUES (cover,
'Cover'),
(Cast(limitationperiod AS
VARCHAR
(10)),
'LimitationPeriod') ) x (value, col
)) d
PIVOT ( Max(value)
FOR new_col IN (cardiaccover,
cardiaclimitationperiod,
cataracteyelenscover,
cataracteyelenslimitationperiod
) ) piv2) mc
ON hc.hcid = mc.hcid
Any suggestions would be appreciated.
Thanks
My suggestion is to break down the query using temporary table, create stored procedure then dump data in the one new table and with the help of that table you can create view:
Store both PIVOT result in tow seperate temp tables as
SELECT * INTO #pvtInfo FROM ( --first PIVOT query
SELECT * INTO #pvtInfoTwo FROM ( --second PIVOT query
Then your final query will be as :
SELECT p.Pid,
hc.hcid,
hc.Accomodation,
ghc.ghcid,
ghc.ProductFeatures,
wp.existing,
wp.acute,
mc.cardiaccover,
mc.cardiaclimitationperiod
FROM TableA p
LEFT JOIN TableB hc ON p.pid = hc.pid
LEFT JOIN TableC ghc ON p.pid = ghc.pid
LEFT JOIN #pvtInfo wp ON hc.hcid = wp.hcid
LEFT JOIN #pvtInfoTwo mc ON hc.hcid = mc.hcid
First you can try then only go with SP and VIEW.
Hope, It will help.

Why does this NOT IN query work as intended, but not this NOT EXISTS query?

Working (NOT IN) retrieves 3 rows:
select DISTINCT d.* from Device d , Company c3
WHERE d.deviceid NOT IN
(
Select d1.deviceid from Device d1, Clone x1
WHERE d1.deviceid = x1.deviceID
AND
(
x1.XPath = 'hi'
OR x1.XPath = 'bye'
)
AND
(
EXISTS ( select * from (SELECT * FROM [dbo].[Split] ('T130SF0W2050', ',')) as s
WHERE x1.Value like '%' + s.items + '%' )
)
)
AND
d.companyid = c3.companyid and c3.companynumber in (SELECT * FROM [dbo].[Split] ('00223200', ','))
Not Working(not exists):
select DISTINCT d.* from Device d , Company c3
WHERE NOT EXISTS
(Select * from Device d1, Clone x1
WHERE d1.deviceid = x1.deviceID
AND
(
x1.XPath = 'hi'
OR x1.XPath = 'bye'
)
AND
(
EXISTS ( select * from (SELECT * FROM [dbo].[Split] ('T130SF0W2050', ',')) as s
WHERE x1.Value like '%' + s.items + '%' )
)
)
AND
d.companyid = c3.companyid and c3.companynumber in (SELECT * FROM [dbo].[Split] ('00223200', ','))
I'm unsure I'm using the exists syntax correct, what should I select from the subquery? I've tried a few different combinations. It won't run if I put WHERE d.deviceid NOT EXISTS
Solution (thanks to Nikola):
add AND d1.deviceid = d.deviceid inside the Exists subquery.
The difference is that the NOT IN query returns devices that match the company and don't match the inner query specification.
For the NOT EXIST query to work as written (where "work as written" refers to returning the same result as the top query), there can't be any devices that exist matching the inner query. If any devices match the inner query at all, the query won't return any results.

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