Cannot use column of outside reference in my inside query - sql

I am using SQL query like below:
SELECT distinct uf.SystemName as System ,uf.SystemId,
(SELECT SUM(CASE WHEN c.SystemId = uf.SystemTypeId THEN 1 ELSE 0 END)
FROM OPENJSON((SELECT TOP 1 CAST(JsonStringColumn AS NVARCHAR(MAX)) FROM RefTable where TagId = (Select top 1 TagId from CSSTAGS where projectid='9abbeecf-15a4-412f-ba0c-358b8f09ac9e')))
WITH (Data NVARCHAR(MAX) AS JSON) a
CROSS APPLY OPENJSON(a.Data)
WITH (System NVARCHAR(MAX) AS JSON) b
CROSS APPLY OPENJSON(b.System)
WITH (SystemId NVARCHAR(MAX) '$.SystemId') c
) As SystemIdExists
FROM Table1 uf
I am not able to use uf.SystemId inside my second select query which throwing below error: Multiple columns are specified in an aggregated expression containing an outer reference.
How can I achieve this?

Adding Where condition to second select query resolved my issue

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

Why Row_Number in a view gives a nullable column

I have a view using a CTE and I want use a row number to simulate a key for my edmx in Visual Studio
ALTER VIEW [dbo].[ViewLstTypesArticle]
AS
WITH cte (IdTypeArticle, IdTypeArticleParent, Logo, Libelle, FullLibelle, Racine) AS
(
SELECT
f.Id AS IdTypeArticle, NULL AS IdParent,
f.Logo, f.Libelle,
CAST(f.Libelle AS varchar(MAX)) AS Expr1,
f.Id AS Racine
FROM
dbo.ArticleType AS f
LEFT OUTER JOIN
dbo.ArticleTypeParent AS p ON p.IdTypeArticle = f.Id
WHERE
(p.IdTypeArticleParent IS NULL)
AND (f.Affichable = 1)
UNION ALL
SELECT
f.Id AS IdTypeArticle, p.IdTypeArticleParent,
f.Logo, f.Libelle,
CAST(parent.Libelle + ' / ' + f.Libelle AS varchar(MAX)) AS Expr1,
parent.Racine
FROM
dbo.ArticleTypeParent AS p
INNER JOIN
cte AS parent ON p.IdTypeArticleParent = parent.IdTypeArticle
INNER JOIN
dbo.ArticleType AS f ON f.Id = p.IdTypeArticle
)
SELECT
*,
ROW_NUMBER() OVER (ORDER BY FullLibelle) AS Id
FROM
(SELECT
IdTypeArticle, IdTypeArticleParent, Logo, Libelle,
FullLibelle, Racine
FROM cte) AS CTE1
When I look in properties of column I see Id bigint ... NULL
And my edmx exclude this view cause don't find a column can be used to key
When I execute my view ID have no null. I've all my row number.
If someone encounter this problem and resolved it ... Thanks
SQL Server generally thinks that columns are NULL-able in views (and when using SELECT INTO).
You can convince SQL Server that this is not the case by using ISNULL():
select *,
ISNULL(ROW_NUMBER() over(ORDER BY FullLibelle), 0) as Id
from . . .
Note: This works with ISNULL() but not with COALESCE() which otherwise has very similar functionality.

SQL Recursive evaluation for each record from separate table (parseJSON)

I'm trying to evaluate a JSON response in SQL for each of the records and merge these into one table.
I'm currently using consuming-json-strings-in-sql-server/ to parse the json which returns a table-valued function,
e.g.
select *
from parseJSON('{"a":1}');
which gives
element_id sequenceNo parent_ID Object_ID NAME StringValue ValueType
1 0 1 NULL a int
2 1 NULL 1 - object
This needs to recurse on each record and merge for each JSON string stored in another table. I'm sure I'm overthinking this again and hoping something simple is around the corner...
As always, any help is greatly appreciated!
I think what you want is this:
select t.*,j.* from yourtable t cross apply parseJSON(t.jsonColumn) j
Do you want to join the returned property from json and column of a table ?
select * from table1 t inner join
(select * from parseJSON('{"a":1}') where Name = 'a') p
ON t.a = p.Name

SQL select join on xml field with xpath expression

I have a following query that can return a result from an xml:
declare #xml xml
select #xml = data from files where id = 1234
select
children.p.value('./speed[1]','float')
from #xml.nodes('root/children') as children(p)
where
children.p.value('./name[1]','nvarchar(max)') = 'something'
This in my case returns a single value, for example 3141
However, I'd like to do multiple selects like this from multiple XMLs.
I can select the xml data as
select id, cast(data as xml) as xml
from files
where id in (1005,51,968,991,992,993,969,970) --for example
I imagine there must be some kind of JOIN that will apply my expression and return a single item for each xml variable in the table, but I am not sure how.
Use apply:
select
f.id, children.p.value('./speed[1]','float')
from files as f
outer apply (select cast(f.data as xml) as xml) as x
outer apply x.xml.nodes('root/children') as children(p)
where
f.id in (1005,51,968,991,992,993,969,970) and
children.p.value('./name[1]','nvarchar(max)') = 'something'

Assign a value to a variable in a select statement and then used to find value in nested select statement

I'm getting the error
A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations.
Here's my SELECT statement.
SELECT A.vendor_id, **#vendor_employee** = A.vendor_employee_id
, B.txt_first_name, B.txt_last_name,
SELECT txt_Vendor_Employee_Detail_Element,
(CASE
WHEN txt_Vendor_Employee_Detail_Value <> ''
AND txt_Vendor_Employee_Detail_Value IS NOT NULL
THEN txt_Vendor_Employee_Detail_Value
ELSE CONVERT(VARCHAR, txt_Vendor_Employee_Detail_Date)
END) AS Vendor_Detail_Element_Value
FROM t_vendor_employee_detail
WHERE vendor_employee_id = **#vendor_employee**)
FROM...
Yes, basically you can't return data and assign variables in the same select statement. What I think you intend to do is a correlated subquery which references an outer value.
That wolud look something like this:
SELECT A.vendor_id, A.vendor_employee_id
, B.txt_first_name, B.txt_last_name,
(SELECT d.txt_Vendor_Employee_Detail_Element
FROM t_vendor_employee_detail d
WHERE d.vendor_employee_id = A.Vendor_employee_id /* references outside the subqquery */)
FROM...
but you are also returning multiple rows in your subquery which should probably be rewritten as a join.
SELECT A.vendor_id, A.vendor_employee_id
, B.txt_first_name, B.txt_last_name,
d.txt_Vendor_Employee_Detail_Element,
(CASE
WHEN D.txt_Vendor_Employee_Detail_Value <> ''
AND d.txt_Vendor_Employee_Detail_Value IS NOT NULL
THEN d.txt_Vendor_Employee_Detail_Value
ELSE CONVERT(VARCHAR, d.txt_Vendor_Employee_Detail_Date)
END) AS Vendor_Detail_Element_Value
FROM vendor_table_A A
INNER JOIN t_vendor_employee_detail d
ON d.vendor_employee_id = A.vendor_employee_id
INNER JOIN vendor_table_B B
ON...
These examples will give you the basic idea but we would really need the whole query to give you a complete solution.
This looks like something that could be rewritten using a JOIN. It's hard to say how without seeing the whole query, but here is an attempt:
SELECT A.vendor_id, A.vendor_employee_id
, B.txt_first_name, B.txt_last_name,
c.txt_Vendor_Employee_Detail_Element,
(CASE
WHEN c.txt_Vendor_Employee_Detail_Value <> ''
AND c.txt_Vendor_Employee_Detail_Value IS NOT NULL
THEN c.txt_Vendor_Employee_Detail_Value
ELSE CONVERT(VARCHAR, c.txt_Vendor_Employee_Detail_Date)
END) AS Vendor_Detail_Element_Value
FROM ...
INNER JOIN t_vendor_employee_detail c
ON c.vendor_employee_id = A.vendor_employee_id
As the error message says, you cannot use a variable in the way you are trying.
You can retrieve and assign data altogether using a merge statement.
Something like this:
DECLARE #ID TABLE (
ID INT
)
MERGE INTO #ID
USING (
select 1 a,2 b,3 c
) as src
ON ( 1 = 2 )
WHEN NOT MATCHED THEN
INSERT (ID)
VALUES (Src.a)
OUTPUT src.b, src.c
;
SELECT * FROM #ID