XML to SQL format - sql

I'm trying to convert my XML string into some SQL elements
unfortunately i have some modification problems
my SQL string :
select #xml
--, #XML.query('Document/Content/Truncated') ff
-- URL --
, #xml.value('(Document/Metadata/Fields/docid)[1]', 'varchar(100)') D_URL
-- title --
, #xml.value('(Document/Metadata/Fields/title)[1]', 'varchar(100)') Title
-- name --
, #xml.value('(Document/Metadata/Facets/Facet/_ne/person)[1]', 'varchar(100)') MD_Name
-- address --
, left((substring(#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') , 18+patindex('%Location & Contact%', (#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') )), 550)),
CHARINDEX ('[MAP]' , (substring(#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') , 18+patindex('%Location & Contact%', (#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') )), 550)) ))Office_Location
-- gender--
, substring(#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') , 18+patindex('%Years in Practice%', (#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') )), 10) Gender
-- phone --
,right(left((substring(#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') , 18+patindex('%Location & Contact%', (#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') )), 550)),
CHARINDEX ('Phone Number' , (substring(#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') , 18+patindex('%Location & Contact%', (#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') )), 550)) )),
CHARINDEX ('(' , (substring(#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') , 18+patindex('%Location & Contact%', (#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') )), 550)) ))Phone
-- speciality --
, substring(#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') , 18+patindex('%Specialties & Qualifications%', (#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') )), 100) Specialities
-- type--
, substring(#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') , 18+patindex('%Doctor Type%', (#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') )), 15) Doctor_Type
-- Explenation --
, substring(#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') , 18+patindex('%Specialty:%', (#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') )), 400) Explenation
-- certification --
, substring(#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') , 18+patindex('%Certifications & Licensure%', (#xml.value('(Document/Content/Text)[1]', 'nvarchar(4000)') )), 200) Board_Certifications
I have a problem ouput in:
output: i just can't catch the damn phone (+332) ....
Specialty: i can't cut all the sentence
any suggestions ?

Related

Error message which I can't explain/solve in sql

This code gives this error which I really don't get (the Select works ok):
'SQL Error [2022] [42601]: SQL compilation error: Missing column
specification'
CREATE OR REPLACE TABLE ANALYSE_PMN.DTE_INSTALL_WFM AS
(
SELECT BUT000.PARTNER AS ZPARTNER ,
BUT000.BPKIND AS SRT ,
FKKVKP.KTOKL AS REKENINGKLASSE ,
EVER.VKONTO AS CONTRACTREKENING ,
EVER.VERTRAG AS CONTRACT ,
TO_CHAR(EVER.EINZDAT, 'YYYYMMDD') AS INHUISDATUM ,
TO_CHAR(EVER.AUSZDAT, 'YYYYMMDD') AS UITHUISDATUM ,
EANL.ANLAGE AS AANSLUITING ,
EANL.SPARTE AS PRODUCT ,
EANLH.ABLEINH AS PORTIE ,
TO_CHAR(EANLH.AB, 'YYYYMMDD') AS VANAF ,
TO_CHAR(EANLH.BIS, 'YYYYMMDD') AS TOT ,
SUBSTR(EANLH.ABLEINH, 2, 4) AS PORTIE_MMDD ,
DTE_PERIODE.PERIODE AS GEPL_AFR_YYYYMM ,
DTE_PERIODE.PERIODE
|| SUBSTR(EANLH.ABLEINH, 4, 2) AS GEPL_AFR_YYYYMMDD ,
NVL(ZZEAN_VERBR_HG, 0) ,
NVL(ZZEAN_VERBR_LG, 0) ,
NVL(ZZEAN_VERBR_HG, 0) + NVL(ZZEAN_VERBR_LG, 0) AS ZZEAN_VERBR ,
NVL(ZZEAN_TERUG_HG, 0) ,
NVL(ZZEAN_TERUG_LG, 0) ,
NVL(ZZEAN_TERUG_HG, 0) + NVL(ZZEAN_TERUG_LG, 0) AS ZZEAN_TERUG ,
(NVL(ZZEAN_VERBR_HG, 0) + NVL(ZZEAN_VERBR_LG, 0)) - (NVL(ZZEAN_TERUG_HG, 0) + NVL(ZZEAN_TERUG_LG, 0)) AS ZZEAN_VERBR_TOTAAL
FROM ANALYSE_PMN.DTE_PERIODE ,
OWNER_OSP.OSP_EVER EVER
JOIN OWNER_OSP.OSP_EANL EANL
ON EANL.ANLAGE = EVER.ANLAGE
JOIN OWNER_OSP.OSP_EANLH EANLH
ON EANLH.ANLAGE = EVER.ANLAGE
JOIN OWNER_OSP.OSP_FKKVKP FKKVKP
ON EVER.VKONTO = FKKVKP.VKONT
JOIN OWNER_OSP.OSP_BUT000 BUT000
ON BUT000.PARTNER = FKKVKP.GPART
WHERE EANL.SPARTE IN ( 'E' ,
'G' )
AND TO_CHAR(EVER.EINZDAT, 'YYYYMMDD') < SUBSTR(DTE_PERIODE.PERIODE, 1, 6)
|| SUBSTR(EANLH.ABLEINH, 4, 2)
AND EVER.AUSZDAT = '9999-12-31'
AND TO_DATE(DTE_PERIODE.PERIODE
|| SUBSTR(EANLH.ABLEINH, 4, 2), 'YYYYMMDD') BETWEEN EANLH.AB AND EANLH.BIS
AND EANL.BEGRU = 'R'
AND EANLH.ABLEINH LIKE 'C%'
AND SUBSTR(DTE_PERIODE.PERIODE, 5, 2) = SUBSTR(EANLH.ABLEINH, 2, 2)
) ;
Some of your columns do not have AS clauses. Can you try this:
CREATE OR REPLACE TABLE ANALYSE_PMN.DTE_INSTALL_WFM AS
(
SELECT BUT000.PARTNER AS ZPARTNER ,
BUT000.BPKIND AS SRT ,
FKKVKP.KTOKL AS REKENINGKLASSE ,
EVER.VKONTO AS CONTRACTREKENING ,
EVER.VERTRAG AS CONTRACT ,
TO_CHAR(EVER.EINZDAT, 'YYYYMMDD') AS INHUISDATUM ,
TO_CHAR(EVER.AUSZDAT, 'YYYYMMDD') AS UITHUISDATUM ,
EANL.ANLAGE AS AANSLUITING ,
EANL.SPARTE AS PRODUCT ,
EANLH.ABLEINH AS PORTIE ,
TO_CHAR(EANLH.AB, 'YYYYMMDD') AS VANAF ,
TO_CHAR(EANLH.BIS, 'YYYYMMDD') AS TOT ,
SUBSTR(EANLH.ABLEINH, 2, 4) AS PORTIE_MMDD ,
DTE_PERIODE.PERIODE AS GEPL_AFR_YYYYMM ,
DTE_PERIODE.PERIODE|| SUBSTR(EANLH.ABLEINH, 4, 2) AS GEPL_AFR_YYYYMMDD ,
NVL(ZZEAN_VERBR_HG, 0) AS ZZEAN_VERBR_HG,
NVL(ZZEAN_VERBR_LG, 0) AS ZZEAN_VERBR_LG,
NVL(ZZEAN_VERBR_HG, 0) + NVL(ZZEAN_VERBR_LG, 0) AS ZZEAN_VERBR ,
NVL(ZZEAN_TERUG_HG, 0) AS ZZEAN_TERUG_HG,
NVL(ZZEAN_TERUG_LG, 0) AS ZZEAN_TERUG_LG,
NVL(ZZEAN_TERUG_HG, 0) + NVL(ZZEAN_TERUG_LG, 0) AS ZZEAN_TERUG ,
(NVL(ZZEAN_VERBR_HG, 0) + NVL(ZZEAN_VERBR_LG, 0)) - (NVL(ZZEAN_TERUG_HG, 0) + NVL(ZZEAN_TERUG_LG, 0)) AS ZZEAN_VERBR_TOTAAL
FROM ANALYSE_PMN.DTE_PERIODE ,
OWNER_OSP.OSP_EVER EVER
JOIN OWNER_OSP.OSP_EANL EANL
ON EANL.ANLAGE = EVER.ANLAGE
JOIN OWNER_OSP.OSP_EANLH EANLH
ON EANLH.ANLAGE = EVER.ANLAGE
JOIN OWNER_OSP.OSP_FKKVKP FKKVKP
ON EVER.VKONTO = FKKVKP.VKONT
JOIN OWNER_OSP.OSP_BUT000 BUT000
ON BUT000.PARTNER = FKKVKP.GPART
WHERE EANL.SPARTE IN ( 'E' ,
'G' )
AND TO_CHAR(EVER.EINZDAT, 'YYYYMMDD') < SUBSTR(DTE_PERIODE.PERIODE, 1, 6)
|| SUBSTR(EANLH.ABLEINH, 4, 2)
AND EVER.AUSZDAT = '9999-12-31'
AND TO_DATE(DTE_PERIODE.PERIODE
|| SUBSTR(EANLH.ABLEINH, 4, 2), 'YYYYMMDD') BETWEEN EANLH.AB AND EANLH.BIS
AND EANL.BEGRU = 'R'
AND EANLH.ABLEINH LIKE 'C%'
AND SUBSTR(DTE_PERIODE.PERIODE, 5, 2) = SUBSTR(EANLH.ABLEINH, 2, 2)
) ;

Removing duplicates from select query output

Could anyone please suggest what is the error in the below query? Actually I want to remove all duplicates from the select query output and fetch only unique rows. Thanks in advance.
select *
from (
select ROW_NUMBER() over (
partition by Dep
, tariffkode
, LinkTariffType
, poliata
, poliatavia
, podiata
, podiatavia
, PreCarriage
, PortTerminalId
, Product
, RoutingOrder
, PrepaidCollect
, isnull(description, '')
, ScaleCalcCode
, isnull(scalefrom, 0)
, isnull(scaleto, 0)
, CurrencyCode
, Base order by LinkTariffType desc
) Record
, *
from (
select tn.LinkTariffType
, tn.Dep
, tn.POLIata
, tn.POLIatavia
, tn.PODIata
, tn.PODIatavia
, tn.CurrencyCode
, tn.LegalEntityID
, tn.Rate
, tn.Base
, tn.Minimum
, tn.NrDescription
, tn.Description
, tn.DateFrom
, tn.DateUntil
, tn.DateCreate
, tn.DateMod
, tn.ModName
, tn.Tariffkode
, tn.ExpiryDate
, tn.PClass
, tn.Maximum
, tn.RoutingOrder
, tn.TariffCompType
, tn.PrePaidCollect
, tn.Product
, tn.IsDeleted
, (
select distinct Location_IATA
from Company
where Called = 'KARL KING'
and LegalEntityID = 1
and IsDeleted = 0
) as PreCarriage
, tn.PortTerminalID
, tn.ScaleFrom
, tn.ScaleTo
, tn.ScaleCalcCode
, tn.Mandatory
, (
select CompanyID
from PlaceOfReceipt
where warehouse = 'KARL KING'
and LegalEntityID = 1
and OfficeID = 13
and IsDeleted = 0
) as WarehouseID
, tn.TariffRelID
, tn.FreeDescription
, 0
, tn.ShipCode
, tn.AgentID
, tn.ContainerTypeID
, tn.CommodityID
, 0 as TempTable
from TariffNew tn
inner join hhInvoiceLines inv
on tn.Tariffkode = inv.NrInvoiceLine
where (
tn.PreCarriage is not null
and tn.PreCarriage != ''
)
and (
tn.POLIata is not null
and tn.POLIata != ''
)
and inv.OfficeID = 13
and inv.IsDeleted = 0
and inv.LegalEntityID = 1
and tn.LegalEntityID = 1
and tn.Dep = 'E'
and tn.IsDeleted = 0
and tn.DateUntil = '2078-12-31 00:00:00'
and tn.Description = 'kgl'
)
) as b
where b.Record = 1
First, you have to define what you want to call "unique rows".
Once you have the set of columns that determines a row is unique, that is the set of columns you use in the partition by part of row_number()
In the code below, uncomment the column set that defines your "unique rows":
select *
from (
select ROW_NUMBER() over (
partition by
Dep
--, tariffkode
--, LinkTariffType
--, poliata
--, poliatavia
--, podiata
--, podiatavia
--, PreCarriage
--, PortTerminalId
--, Product
--, RoutingOrder
--, PrepaidCollect
--, isnull(description, '')
--, ScaleCalcCode
--, isnull(scalefrom, 0)
--, isnull(scaleto, 0)
--, CurrencyCode
--, Base
order by LinkTariffType desc
) Record
, *
from (
select tn.LinkTariffType
, tn.Dep
, tn.POLIata
, tn.POLIatavia
, tn.PODIata
, tn.PODIatavia
, tn.CurrencyCode
, tn.LegalEntityID
, tn.Rate
, tn.Base
, tn.Minimum
, tn.NrDescription
, tn.Description
, tn.DateFrom
, tn.DateUntil
, tn.DateCreate
, tn.DateMod
, tn.ModName
, tn.Tariffkode
, tn.ExpiryDate
, tn.PClass
, tn.Maximum
, tn.RoutingOrder
, tn.TariffCompType
, tn.PrePaidCollect
, tn.Product
, tn.IsDeleted
, (
select distinct Location_IATA
from Company
where Called = 'KARL KING'
and LegalEntityID = 1
and IsDeleted = 0
) as PreCarriage
, tn.PortTerminalID
, tn.ScaleFrom
, tn.ScaleTo
, tn.ScaleCalcCode
, tn.Mandatory
, (
select CompanyID
from PlaceOfReceipt
where warehouse = 'KARL KING'
and LegalEntityID = 1
and OfficeID = 13
and IsDeleted = 0
) as WarehouseID
, tn.TariffRelID
, tn.FreeDescription
, 0 as UnnamedColumn
, tn.ShipCode
, tn.AgentID
, tn.ContainerTypeID
, tn.CommodityID
, 0 as TempTable
from TariffNew tn
inner join hhInvoiceLines inv on tn.Tariffkode = inv.NrInvoiceLine
where tn.PreCarriage is not null
and tn.PreCarriage != ''
and tn.POLIata is not null
and tn.POLIata != ''
and inv.OfficeID = 13
and inv.IsDeleted = 0
and inv.LegalEntityID = 1
and tn.LegalEntityID = 1
and tn.Dep = 'E'
and tn.IsDeleted = 0
and tn.DateUntil = '2078-12-31 00:00:00'
and tn.Description = 'kgl'
) as s
) as b
where b.Record = 1

XML Conversion issue

Getting the following error; "Error converting data type varchar to numeric".
This happens when trying to select data from an XML input. Below is the code:
DECLARE #XmlIn XML = '<rec>
<targetId>10</targetId>
<categoryId>4</categoryId>
<percent>2</percent>
<AgreementDurationMin></AgreementDurationMin>
<AgreementDurationMax></AgreementDurationMax>
</rec>'
INSERT INTO WizzTable
( CommissionTargetId ,
CommissionPercentageCategoryId ,
Percentage ,
AgreementDurationMin ,
AgreementDurationMax
)
SELECT targetId = NULLIF(cb.n.value('(targetId)[1]', 'INT'),
'') ,
categoryId = NULLIF(cb.n.value('(categoryId)[1]',
'SMALLINT'), '') ,
percentage = NULLIF(cb.n.value('(percent)[1]',
'DECIMAL(17,2)'), '') ,
AgreementDurationMin = ISNULL(NULLIF(cb.n.value('(AgreementDurationMin)[1]',
'INT'), ''), 0) ,
AgreementDurationMax = NULLIF(cb.n.value('(AgreementDurationMax)[1]',
'INT'), '')
FROM #XmlIn.nodes('rec') cb ( n )
WHERE cb.n.value('(percent/text())[1]', 'INT') > 0
Any ideas? Thanks!
What percent element type? you try to convert it to DECIMAL(17,2) in your select; but in your where clause, it is INT.
The error complains your Nullif default value. Sql cannot convert a '' to a decimal.
Fix:
DECLARE #XmlIn XML = '<rec>
<targetId>10</targetId>
<categoryId>4</categoryId>
<percent>2</percent>
<AgreementDurationMin></AgreementDurationMin>
<AgreementDurationMax></AgreementDurationMax>
</rec>'
INSERT INTO WizzTable
( CommissionTargetId ,
CommissionPercentageCategoryId ,
Percentage ,
AgreementDurationMin ,
AgreementDurationMax
)
SELECT targetId = NULLIF(cb.n.value('(targetId)[1]', 'INT'),
'') ,
categoryId = NULLIF(cb.n.value('(categoryId)[1]',
'SMALLINT'), '') ,
percentage = NULLIF(cb.n.value('(percent)[1]',
'DECIMAL(17,2)'), '0') ,
AgreementDurationMin = ISNULL(NULLIF(cb.n.value('(AgreementDurationMin)[1]',
'INT'), ''), 0) ,
AgreementDurationMax = NULLIF(cb.n.value('(AgreementDurationMax)[1]',
'INT'), '')
FROM #XmlIn.nodes('rec') cb ( n )
WHERE cb.n.value('(percent/text())[1]', 'DECIMAL(17,2)') > 0
You are setting the empty string here
... = NULLIF(something,'')
The empty string is not valid in an numeric context. The types must be the same for expression1 and expression2: https://msdn.microsoft.com/en-us/library/ms177562.aspx
Try it like this:
SELECT targetId = NULLIF(cb.n.value('(targetId)[1]', 'INT'),
0) ,
categoryId = NULLIF(cb.n.value('(categoryId)[1]',
'SMALLINT'), 0) ,
percentage = NULLIF(cb.n.value('(percent)[1]',
'DECIMAL(17,2)'), 0) ,
AgreementDurationMin = ISNULL(NULLIF(cb.n.value('(AgreementDurationMin)[1]',
'INT'), 0), 0) ,
AgreementDurationMax = NULLIF(cb.n.value('(AgreementDurationMax)[1]',
'INT'), 0)
FROM #XmlIn.nodes('rec') cb ( n )
WHERE cb.n.value('(percent/text())[1]', 'INT') > 0

Column alias for VALUES ( ) syntax

Here's some SQL:
select T.*
FROM (
values ( '2014-05-30 17:26:32.749' , 'Casual shirt ' ) , ( '2014-05-30 17:26:32.749' , 'Casual shirt-White-Small ' ) , ( '2014-05-30 17:26:32.749' , 'Casual shirt-Blue-Medium ' ) , ( '2014-05-30 17:26:32.749' , 'Cords ' ) , ( '2014-05-30 17:26:32.749' , 'Bodysuit ' ) , ( '2014-05-30 17:26:32.749' , 'Cords-Black-29W x 28L ' ) , ( '2014-05-30 17:26:32.749' , 'Bodysuit-Black-Petit ' ) , ( '2014-05-30 17:26:32.749' , 'Cords-Brown-29W x 28L ' ) , ( '2014-05-30 17:26:32.749' , 'Classic pleated dress pant ' ) , ( '2014-05-30 17:26:32.749' , 'Classic pleated dress pant-Black-29W x 32L ' ) , ( '2014-05-30 17:26:32.749' , 'Dress shirt ' ) , ( '2014-05-30 17:26:32.749' , 'Dress shirt-White-15 ' ) , ( '2014-05-30 17:26:32.749' , 'Dress shirt-White-16 ' )
) T
;
It returns columns "1" and "2". How to change it so it returns named columns? Is it possible without using sysdummy1 ?
You can add the column names to T:
select T.*
FROM (values ( '2014-05-30 17:26:32.749' , 'Casual shirt ' ) ,
( '2014-05-30 17:26:32.749' , 'Casual shirt-White-Small ' ) ,
( '2014-05-30 17:26:32.749' , 'Casual shirt-Blue-Medium ' ) ,
( '2014-05-30 17:26:32.749' , 'Cords ' ) ,
( '2014-05-30 17:26:32.749' , 'Bodysuit ' ) ,
. . .
) T(col1, col2);

Optimizing T-SQL query which constracts the same subtable twice

I want to optimize this query
WITH CTE AS
(
SELECT
KladrItemName _KladrItemName
, WordPositionKladrItem _WordPositionKladrItem
, WordPositionAddressString _WordPositionAddressString
, StartPosition _StartPosition
, EndPosition _EndPosition
, Metric _Metric
, IsConstruction _IsConstruction
, WordsCount _WordsCount
, Indeces _Indeces
, WordPositionAddressString _StartWordIndex
, WordPositionAddressString _EndWordIndex
, 1 _StepNumber
FROM
(
SELECT
dbo.tKladrItems.KladrItemName
, dbo.tFoundWords.WordFromAddressString
, dbo.tFoundWords.WordFromKladr
, dbo.tFoundWords.WordPosition AS WordPositionAddressString
, dbo.tWordKladrItems.wordNumber AS WordPositionKladrItem
, dbo.tFoundWords.StartPosition
, dbo.tFoundWords.EndPosition
, dbo.tFoundWords.Metric
, dbo.tFoundWords.IsConstruction
, dbo.tKladrItems.WordsCount
, dbo.tKladrItems.Indeces
FROM
dbo.tWordsFromKladr JOIN dbo.tWordKladrItems ON dbo.tWordsFromKladr.ID = dbo.tWordKladrItems.wordID
JOIN dbo.tFoundWords ON dbo.tFoundWords.WordFromKladr = dbo.tWordsFromKladr.WordFromKladr
JOIN dbo.tKladrItems ON dbo.tWordKladrItems.kladrItemID = dbo.tKladrItems.id
)T
UNION ALL
SELECT
KladrItemName
, WordPositionKladrItem
, WordPositionAddressString
, CASE WHEN StartPosition _EndPosition THEN EndPosition ELSE _EndPosition END -- MAX
, CAST(Metric + _Metric AS numeric(20, 10))
, IsConstruction + _IsConstruction
, WordsCount
, Indeces
, CASE WHEN _StartWordIndex WordPositionAddressString THEN _EndWordIndex ELSE WordPositionAddressString END
, 1 + _StepNumber
FROM
(
SELECT
dbo.tKladrItems.KladrItemName
, dbo.tFoundWords.WordFromAddressString
, dbo.tFoundWords.WordFromKladr
, dbo.tFoundWords.WordPosition AS WordPositionAddressString
, dbo.tWordKladrItems.wordNumber AS WordPositionKladrItem
, dbo.tFoundWords.StartPosition
, dbo.tFoundWords.EndPosition
, dbo.tFoundWords.Metric
, dbo.tFoundWords.IsConstruction
, dbo.tKladrItems.WordsCount
, dbo.tKladrItems.Indeces
FROM
dbo.tWordsFromKladr JOIN dbo.tWordKladrItems ON dbo.tWordsFromKladr.ID = dbo.tWordKladrItems.wordID
JOIN dbo.tFoundWords ON dbo.tFoundWords.WordFromKladr = dbo.tWordsFromKladr.WordFromKladr
JOIN dbo.tKladrItems ON dbo.tWordKladrItems.kladrItemID = dbo.tKladrItems.id
) AS Tab JOIN CTE ON
Tab.KladrItemName = CTE._KladrItemName
AND Tab.WordPositionKladrItem > CTE._WordPositionKladrItem
AND Tab.WordPositionAddressString > CTE._WordPositionAddressString
)
SELECT DISTINCT
_KladrItemName KladrItemName
, _StartPosition StartPosition
, _EndPosition EndPosition
, _Metric SumMetric
, _IsConstruction SumIsConstruction
, _Indeces Indeces
FROM
CTE
WHERE
_StepNumber = _WordsCount
AND (_IsConstruction = 0 or (_IsConstruction = 1 and _WordsCount > 1))
AND _EndWordIndex - _StartWordIndex + 1 = _WordsCount
option (maxrecursion 0)
So that the table
SELECT
dbo.tKladrItems.KladrItemName
, dbo.tFoundWords.WordFromAddressString
, dbo.tFoundWords.WordFromKladr
, dbo.tFoundWords.WordPosition AS WordPositionAddressString
, dbo.tWordKladrItems.wordNumber AS WordPositionKladrItem
, dbo.tFoundWords.StartPosition
, dbo.tFoundWords.EndPosition
, dbo.tFoundWords.Metric
, dbo.tFoundWords.IsConstruction
, dbo.tKladrItems.WordsCount
, dbo.tKladrItems.Indeces
FROM
dbo.tWordsFromKladr JOIN dbo.tWordKladrItems ON dbo.tWordsFromKladr.ID = dbo.tWordKladrItems.wordID
JOIN dbo.tFoundWords ON dbo.tFoundWords.WordFromKladr = dbo.tWordsFromKladr.WordFromKladr
JOIN dbo.tKladrItems ON dbo.tWordKladrItems.kladrItemID = dbo.tKladrItems.id
builds only once. But when I declare it as a temporary table, the execution time increases several times. Is there a way to optimize it by building this table once? Is there a way to optimaze it somehow else?
Thank you for help.
Use:
WITH base_table AS (
SELECT wki.KladrItemName,
fw.WordFromAddressString,
fw.WordFromKladr,
fw.WordPosition AS WordPositionAddressString,
tfk.wordNumber AS WordPositionKladrItem,
fw.StartPosition,
fw.EndPosition,
fw.Metric,
fw.IsConstruction,
wki.WordsCount,
wki.Indeces
FROM dbo.tWordsFromKladr tfk
JOIN dbo.tWordKladrItems wki ON wki.wordID = tkf.ID
JOIN dbo.tFoundWords fw ON fw.WordFromKladr = tfk.WordFromKladr
JOIN dbo.tKladrItems ki ON ki.id = wki.kladrItemID),
cte AS (
SELECT bt.*
FROM base_table bt
UNION ALL
SELECT KladrItemName,
WordPositionKladrItem,
WordPositionAddressString,
CASE WHEN StartPosition _EndPosition THEN EndPosition ELSE _EndPosition END -- MAX,
CAST(Metric + _Metric AS numeric(20, 10)),
IsConstruction + _IsConstruction,
WordsCount,
Indeces,
CASE WHEN _StartWordIndex WordPositionAddressString THEN _EndWordIndex ELSE WordPositionAddressString END,
1 + _StepNumber
FROM base_table)
...
You can create two CTEs in a statement. Try this:
WITH Sub As
(SELECT i.KladrItemName,
f.WordFromAddressString, f.WordFromKladr,
f.WordPosition WordPositionAddressString,
wi.wordNumber WordPositionKladrItem,
f.StartPosition, f.EndPosition, f.Metric,
f.IsConstruction, i.WordsCount, i.Indeces
FROM dbo.tWordsFromKladr w
JOIN dbo.tWordKladrItems wi ON wi.ID = i.wordID
JOIN dbo.tFoundWords f ON f.WordFromKladr = w.WordFromKladr
JOIN dbo.tKladrItems i ON wi.kladrItemID = i.id ),
CTE As
(SELECT KladrItemName _KladrItemName,
WordPositionKladrItem _WordPositionKladrItem,
WordPositionAddressString _WordPositionAddressString,
StartPosition _StartPosition ,
EndPosition _EndPosition,
Metric _Metric, IsConstruction _IsConstruction,
WordsCount _WordsCount,
Indeces _Indeces,
WordPositionAddressString _StartWordIndex ,
WordPositionAddressString _EndWordIndex,
1 _StepNumber
FROM Sub T
UNION ALL
SELECT KladrItemName, WordPositionKladrItem, WordPositionAddressString,
CASE WHEN StartPosition < _EndPosition
THEN EndPosition ELSE _EndPosition END, -- Max
CAST(Metric + _Metric AS numeric(20, 10)),
IsConstruction + _IsConstruction,
WordsCount, Indeces,
CASE WHEN _StartWordIndex WordPositionAddressString
THEN _EndWordIndex ELSE WordPositionAddressString END,
1 + _StepNumber
FROM Sub Tab
JOIN CTE
ON Tab.KladrItemName = CTE._KladrItemName
AND Tab.WordPositionKladrItem > CTE._WordPositionKladrItem
AND Tab.WordPositionAddressString > CTE._WordPositionAddressString)
SELECT DISTINCT _KladrItemName KladrItemName,
_StartPosition StartPosition, _EndPosition EndPosition,
_Metric SumMetric,_IsConstruction SumIsConstruction,
_Indeces Indeces
FROM CTE
WHERE_StepNumber = _WordsCount
AND (_IsConstruction = 0 or (_IsConstruction = 1 and _WordsCount > 1))
AND _EndWordIndex - _StartWordIndex + 1 = _WordsCountoption
(maxrecursion 0)