unpivot result from temporary table - sql

i try to get the result in an unpivot resultset but with more column I've never used this technique.
I got a temporary table.. with many field... but focus on listing below.
SELECT
u.IDNode_u,
l.lev_u
from #Slugs
unpivot
(
IDNode_u for node in (IDNodo, IDNodoPadre, [IDNodoPadre-2], [IDNodoPadre-3], [IDNodoPadre-4], [IDNodoPadre-5], [IDNodoPadre-6])
) u
unpivot
(
lev_u for level in (LivelloTop, [LivelloTop-1], [LivelloTop-2], [LivelloTop-3], [LivelloTop-4], [LivelloTop-5], [LivelloTop-6])
) l
The query is ok only with the first unpivot, with second add I got error:
"The multi-part identifier "u.IDNodo_u" could not be bound.", but I think is bound to the second unpivot.
Can someone with me some advise?
Alen Italy.

I think the easiest way to unpivot is to use cross apply:
select u.IDNode_u, l.lev_u
from #slugs s cross apply
(values (IDNodo), (IDNodoPadre), ([IDNodoPadre-2]), ([IDNodoPadre-3]),
([IDNodoPadre-4]), ([IDNodoPadre-5]), ([IDNodoPadre-6])
) u(IDNode_u) cross apply
(values (LivelloTop), ([LivelloTop-1]), ([LivelloTop-2]),
([LivelloTop-3]), ([LivelloTop-4]), ([LivelloTop-5]),
([LivelloTop-6])
) l(lev_u);
EDIT:
I think you intend:
select ul.IDNode_u, ul.lev_u
from #slugs s cross apply
(values (IDNodo, LivelloTop),
(IDNodoPadre, [LivelloTop-1]),
([IDNodoPadre-2], [LivelloTop-2]),
([IDNodoPadre-3], [LivelloTop-3]),
([IDNodoPadre-4], [LivelloTop-4]),
([IDNodoPadre-5], [LivelloTop-5]),
([IDNodoPadre-6], [LivelloTop-6])
) ul(IDNode_u, lev_u) ;

Related

Trino implement a function like regexp_split_to_table()?

Everyone,
I am new to Trino, and I find no function in Trino like regexp_split_to_table() in GreenPlum or PostgreSQL. How can I approach that?
select regexp_split_to_table( sensor_type, E',+' ) as type from hydrology.device_info;
There is regexp_split(string, pattern) function, returns array, you can unnest it.
Demo:
select s.str as original_str, u.str as exploded_value
from
(select 'one,two,,,three' as str)s
cross join unnest(regexp_split(s.str,',+')) as u(str)
Result:
original_str exploded_value
one,two,,,three one
one,two,,,three two
one,two,,,three three

Cross apply missing keyword

I am writing a query in Oracle(11g):
select DBTM,AVNR from E_MW_01Min_MIT m
cross apply(
select Avnr,XDatum1 from E_MW_01DAY_MEX d
where d.AVnr = m.avnr
and d.XDatum1 = m.DBTM
)
but it gives me the error
ORA-00905: missing keyword
where is the problem?
Thank you
This keywords (CROSS APPLY or OUTER APPLY) is introduced in Oracle 12c version.
You can see this link :
cross apply giving missing keyword error
cross apply is not available in that version of Oracle. Just use join instead:
select m.DBTM, d.AVNR
from E_MW_01Min_MIT m JOIN
E_MW_01DAY_MEX d
ON d.AVnr = m.avnr AND d.XDatum1 = m.DBTM ;
This is actually more easily expressed using JOIN, so I see no advantage to attempting APPLY even if the database does support it.

Error when using UNPIVOT in SQL Server

I have the following query:
SELECT STDEV(Value) as Value, TimeOfTest as Date
FROM myTable
unpivot
(
value
for col in (WS1, WS2, WS3, WS4, WS5, WS6, WS7, WS8, WS9, WS10, WS11,
WS12, WS13, WS14, WS15, WS16, WS17, WS18, WS19, WS20)
) un
GROUP BY TimeOfTest
ORDER BY TimeOfTest DESC
but I get an SQL server 2008 error: Incorrect syntax near the keyword 'FOR'
Would anyone know the reason why? The syntax looks correct.
Just use APPLY.
SELECT t.TimeOfTest, STDEV(ws) as Value
FROM myTable t CROSS APPLY(
(VALUES (WS1), (WS2), . . . (WS20)) v(ws)
GROUP BY t.TimeOfTest
ORDER BY t.TimeOfTest DESC;
APPLY implements something called a "lateral join". This is a very powerful (and ANSI-standard) construct, that can be used for many things beyond unpivoting. On the other hand, unpivot is very specific syntax that is used for only one purpose . . . and as you have found, may not work well other constructs such as GROUP BY (I think you could resolve your issue by using a subquery).

SQL to XML not able to create proper XMLNAMESPACE due to quotation marks (I think)

I have the following query:
WITH XMLNAMESPACES ('CommonImport StudentRecordCount="1"
xsi:schemaLocation="http://collegeboard.org/CommonImport CommonImport.xsd"
xmlns="http://collegeboard.org/CommonImport"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' AS CommonImport)
SELECT B.award_year_token AS [StudentID/AwardYearToken]
,A.student_ssn AS [StudentID/SSN]
,A.last_name AS [StudentName/LastName]
,A.first_name AS [StudentName/FirstName]
,A.alternate_id AS [StudentName/AlternateID]
,'2807' AS [CustomStrings/CustomString/FieldID]
,C.processed_status AS [CustomStrings/CustomString/Value]
,'2506' AS [CustomDates/CustomDate/FieldID]
,CAST (C.date_processed AS DATE) AS [CustomDates/CustomDate/Value]
FROM [dbo].[student] A INNER JOIN [stu_award_year] B ON A.[student_token] = B.[student_token]
LEFT OUTER JOIN [dbo].[isir_convert_data] C ON A.[student_ssn] = C.[ssn] AND B.award_year_token = C.award_year_token
--LEFT OUTER JOIN [user_string] E ON B.[stu_award_year_token] = E.[stu_award_year_token]
--WHERE B.AWARD_YEAR_TOKEN = 2018 --For 18-19 year.
WHERE B.AWARD_YEAR_TOKEN = 2017 --For 17-18 year.
AND C.processed_status ='B'
AND C.date_processed = (SELECT MAX (X.date_processed)
FROM isir_convert_data X
WHERE C.ssn = X.ssn)
FOR XML PATH('Student'), ROOT('CommonImport')
The output is unusable due to the mishandling of the quotation marks. It looks like the following:
<CommonImport xmlns:CommonImport="CommonImport StudentRecordCount="1" xsi:schemaLocation="http://collegeboard.org/CommonImport CommonImport.xsd" xmlns="http://collegeboard.org/CommonImport" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"">
I am generating this via SQL Server. Can you offer any advice on how to properly create the XML Tag? And if I'm not properly using the XMLNAMESPACE function, please let me know. Thank you for considering.
You must distinguish between
the declaration of a namespace and
the usage of a namespace
It seems to me, that StudentRecordCount should be an attribute in the <CommonImport> node, same with schemaLocation. The second attribute is living within the xmlns:xsi-namespace.
You did not state the expected output, but my magic crystal ball showed me, that you might need this:
WITH XMLNAMESPACES (DEFAULT 'http://collegeboard.org/CommonImport'
,'http://www.w3.org/2001/XMLSchema-instance' AS xsi)
SELECT 1 AS [#StudentRecordCount]
,'http://collegeboard.org/CommonImport CommonImport.xsd' AS [#xsi:schemaLocation]
,'SomeOtherData' AS [Student/SomeElement]
FOR XML PATH('CommonImport');
the result
<CommonImport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://collegeboard.org/CommonImport"
StudentRecordCount="1"
xsi:schemaLocation="http://collegeboard.org/CommonImport CommonImport.xsd">
<Student>
<SomeElement>SomeOtherData</SomeElement>
</Student>
</CommonImport>
If this does not help enough, please read about how to create a MCVE and provide sample data and expected output.
UPDATE 1
This is - roughly - what you need, but the namespaces are repeated. This is a known and annoying issue. Not wrong, the result is perfectly okay, but bloated.
WITH XMLNAMESPACES (DEFAULT 'http://collegeboard.org/CommonImport'
,'http://www.w3.org/2001/XMLSchema-instance' AS xsi)
,cte AS
(
SELECT object_id,name FROM sys.objects
)
SELECT COUNT(*) AS [#RecordCount]
,'http://collegeboard.org/CommonImport CommonImport.xsd' AS [#xsi:schemaLocation]
,(
SELECT *
FROM cte
FOR XML PATH('Object'),TYPE
)
FROM cte
FOR XML PATH('CommonImport');
UPDATE 2
An ugly workaround
WITH cte AS
(
SELECT object_id,name FROM sys.objects
)
SELECT
CAST(REPLACE(REPLACE(REPLACE(CAST(
(
SELECT COUNT(*) AS [#RecordCount]
,'http://collegeboard.org/CommonImport CommonImport.xsd' AS [#xsi_schemaLocation] --<-- "xsi:" is replaced with "xsi_"
,'http://collegeboard.org/CommonImport' AS [#_xmlns_] --<-- "xmlns" is not allowed
,'http://www.w3.org/2001/XMLSchema-instance' AS [#_xmlns_xsi] --<-- Same with "xmlns:xsi"
,(
SELECT *
FROM cte
FOR XML PATH('Object'),TYPE
)
FROM cte
FOR XML PATH('CommonImport'),TYPE) AS nvarchar(MAX)),'xsi_','xsi:'),'_xmlns_',' xmlns'),'xmlnsxsi','xmlns:xsi') AS XML);
Alternatively you might create the whole thing without namespaces at all and add the namespace declaration with string methods at the end.

Update UDF names stored in table to add parameter value

I have thousands of UDF names stored in table and executed dynamically where it is required. The problem is I have added one new parameter unit to the function dbo.GetStockPrice(6544,1) so I need to send one more parameter value for now 1 bue it can be any and the data should be changed to dbo.GetStockPrice(6544,1,1) for all the rows where dbo.GetStockPrice is exist. So I am seeking for the query to update these all at once.
Sample Data
DECLARE #table AS TABLE(id INT, UDF VARCHAR(1000))
INSERT INTO #table VALUES
(7774,'dbo.GetStockPrice(1211,1)*dbo.GetStockPrice(1211,1)'),
(7775,'dbo.GetStockPrice(232,1)'),
(7778,'dbo.GetStockPrice(6456,1)'),
(7780,'dbo.GetStockPrice(34,1)'),
(7784,'dbo.FNACondition(dbo.FNAMargin(1,NULL,0), 0, dbo.GetStockPrice(654,1)+1)'),
(7786,'dbo.GetStockPrice(9876,1)'),
(7906,'dbo.GetStockPrice(5565,1)'),
(7911,'dbo.GetStockPrice(7886,1)'),
(7912,'dbo.GetStockPrice(87,1)'),
(8403,'dbo.PriceValue(479,NULL,NULL)*dbo.GetStockPrice(6544,1)+dbo.FNAMargin(1,NULL,0)')
Expected Output:
7774 dbo.GetStockPrice(1211,1,1)*dbo.GetStockPrice(1211,1,1)
7775 dbo.GetStockPrice(232,1,1)
so on......
I am still trying with REPLACE, SUBSTRING but unable to come out with any solution. Getting difficulties with it's different length and position in the row.
Seeking Help !! Thank you in Advance :)
Try it with this approach:
DECLARE #table AS TABLE(id INT, UDF VARCHAR(1000))
INSERT INTO #table VALUES
(7774,'dbo.GetStockPrice(1211,1)*dbo.GetStockPrice(1211,1)'),
(7775,'dbo.GetStockPrice(232,1)'),
(7778,'dbo.GetStockPrice(6456,1)'),
(7780,'dbo.GetStockPrice(34,1)'),
(7784,'dbo.FNACondition(dbo.FNAMargin(1,NULL,0), 0, dbo.GetStockPrice(654,1)+1)'),
(7786,'dbo.GetStockPrice(9876,1)'),
(7906,'dbo.GetStockPrice(5565,1)'),
(7911,'dbo.GetStockPrice(7886,1)'),
(7912,'dbo.GetStockPrice(87,1)'),
(7913,'dbo.Blah(87,1)'),
(8403,'dbo.PriceValue(479,NULL,NULL)*dbo.GetStockPrice(6544,1)+dbo.FNAMargin(1,NULL,0)');
--The query
WITH SplitToParts AS
(
SELECT t.*
,A.parted
,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS PartNr
,B.part.value('text()[1]','nvarchar(max)') AS Part
FROM #table AS t
CROSS APPLY(SELECT CAST('<x>' + REPLACE((SELECT t.UDF AS [*] FOR XML PATH('')),'dbo.GetStockPrice(','</x><x>$$$FoundIt$$$</x><x>') + '</x>' AS XML)) AS A(parted)
CROSS APPLY parted.nodes(N'/x') AS B(part)
WHERE UDF LIKE '%dbo.GetStockPrice(%'
)
,modified AS
(
SELECT *
,CASE WHEN LAG(stp.Part) OVER(PARTITION BY id ORDER BY PartNr)='$$$FoundIt$$$' THEN STUFF(stp.Part,CHARINDEX(')',stp.Part),0,',1') ELSE stp.Part END AS Added
FROM SplitToParts AS stp
)
SELECT t2.*
,(
SELECT REPLACE(m.added,'$$$FoundIt$$$','dbo.GetStockPrice(')
FROM modified AS m
WHERE m.id=t2.id
ORDER BY m.PartNr
FOR XML PATH(''),TYPE
).value('.','nvarchar(max)')
FROM #table AS t2
WHERE UDF LIKE '%dbo.GetStockPrice(%';
The result
7774 dbo.GetStockPrice(1211,1,1)*dbo.GetStockPrice(1211,1,1)
7775 dbo.GetStockPrice(232,1,1)
7778 dbo.GetStockPrice(6456,1,1)
7780 dbo.GetStockPrice(34,1,1)
7784 dbo.FNACondition(dbo.FNAMargin(1,NULL,0), 0, dbo.GetStockPrice(654,1,1)+1)
7786 dbo.GetStockPrice(9876,1,1)
7906 dbo.GetStockPrice(5565,1,1)
7911 dbo.GetStockPrice(7886,1,1)
7912 dbo.GetStockPrice(87,1,1)
8403 dbo.PriceValue(479,NULL,NULL)*dbo.GetStockPrice(6544,1,1)+dbo.FNAMargin(1,NULL,0)
Some explanation: The string will be cut in parts using your function's name as splitter. Gladfully you tagged this with [sql-server-2012] so you can use LAG(). This will test the previous element, if it is $$$FoundIt$$$. In this case the first closing bracket will get an additional ,1. The rest is reconcatenation.
Attention: If your call might include a computed value such as
dbo.GetStockPrice(1211,(1+2))
or
dbo.GetStockPrice(dbo.SomeOtherFunc(1),1)
...the first closing bracket is the wrong place to insert the ,1. But this would get really tricky... You'd have to run through it, char by char, and count the opening brackets to find the related closing one.