Delete XML Child Node Element in SQL Server 2008 - sql-server

I have this xml, I want to insert it into temp table including the values inside <salesorpurchase> node in a single row. Is this possible?
Or can you tell me how to remove the <SalesOrPurchase> without removing its inner text`?
<ItemServiceRet>
<ListID>80000012-1302270176</ListID>
<EditSequence>1302270195</EditSequence>
<Name>2nd Floor Shop</Name>
<FullName>2nd Floor Shop</FullName>
<IsActive>true</IsActive>
<SalesOrPurchase>
<Price>0.00</Price>
<AccountRef>
<ListID>800000B3-1302260225</ListID>
<FullName>Rent Income:Rent income 2ND FL:2nd Floor Shops</FullName>
</AccountRef>
</SalesOrPurchase>
</ItemServiceRet>
<ItemServiceRet>
<ListID>80000002-1277187768</ListID>
<EditSequence>1463398389</EditSequence>
<Name>VAT 16%</Name>
<FullName>VAT 16%</FullName>
<IsActive>true</IsActive>
<SalesOrPurchase>
<PricePercent>16.00</PricePercent>
<AccountRef>
<ListID>6B0000-1224749077</ListID>
<FullName>Vat account</FullName>
</AccountRef>
</SalesOrPurchase>
</ItemServiceRet>

1) Try following query to insert data from every ItemServiceRet element into one row (in this case, because there are two ItemServiceRet elements two rows will be inserted):
DECLARE #XmlData XML = N'
<ItemServiceRet>
<ListID>80000012-1302270176</ListID>
<EditSequence>1302270195</EditSequence>
<Name>2nd Floor Shop</Name>
<FullName>2nd Floor Shop</FullName>
<IsActive>true</IsActive>
<SalesOrPurchase>
<Price>0.00</Price>
...
</ItemServiceRet>'
SELECT ListID = y.XmlCol.value('(ListID)[1]', 'VARCHAR(19)'),
EditSequence = y.XmlCol.value('(EditSequence)[1]', 'INT'),
-- ...
Price = y.XmlCol.value('(SalesOrPurchase/Price)[1]', 'NUMERIC(9,2)'),
PricePercent = y.XmlCol.value('(SalesOrPurchase/PricePercent)[1]', 'NUMERIC(9,2)'),
ListID2 = y.XmlCol.value('(SalesOrPurchase/AccountRef/ListID)[1]', 'VARCHAR(19)')
INTO #Items
FROM (VALUES (#XmlData)) x(XmlCol)/*or #XmlData.nodes*/
CROSS APPLY x.XmlCol.nodes(N'ItemServiceRet') y(XmlCol)
/*
Results:
(2 row(s) affected)
*/
This solution is using two XML methods: nodes (shred XML into many rows) and value (it extract one value from current node/element).
2) Second solution is "deleting" the SalesOrderHeader node thus:
SELECT x.XmlCol.query('
for $i in (ItemServiceRet)
return
<ItemServiceRet>
<ListID>{$i/ListID/text()}</ListID>
<IsActive>{$i/IsActive/text()}</IsActive>
<Price>{$i/SalesOrPurchase/Price/text()}</Price>
<PricePercent>{$i/SalesOrPurchase/PricePercent/text()}</PricePercent>
<AccountRef>
<ListID>{$i/SalesOrPurchase/AccountRef/ListID/text()}</ListID>
<FullName>{$i/SalesOrPurchase/AccountRef/FullName/text()}</FullName>
</AccountRef>
</ItemServiceRet>
') AS NewXmlCol
FROM (SELECT (#XmlData)) x(XmlCol)

Related

SQL Server - selecting a specific ID from a table

I will explain what I have done so far and ask my question at the end.
First I created my external & internal variables (note that #EDelivery is a table type that included the columns FoodID and Quantity):
#EDelivery DeliveryTblType readonly
Declare #NumberOfMinutes smallint, #FoodWeight int, #WeightCapacity int,
#DroneID int, #TimeOfWeek varchar
I then read this in, giving me the total weight of all items ordered and read in the weight capacity from the DronesTbl:
select #FoodWeight = SUM(FoodWeight * Quantity)
from #EDelivery as del
inner join Foods on del.FoodID = Foods.FoodID
select #WeightCapacity = Drones.WeightCapacity
from dbo.Drones
My question is how do I select a specific drone to compare its weightcapacity to the food total weight
You need to set the variable #WeightCapacity according to the #droneid value. Right now, you are setting this variable to last drone in your drones table.
If you change your second query to what's below then it should work.
select #WeightCapacity =
Drones.WeightCapacity
from dbo.Drones
where DroneID =#droneID

Updating one table's column in SQL Server from another

I have a table of measurements from weather stations, with station names (in Hebrew):
I also have created a table of those weather stations with their latitudes and longitudes:
I've written a query that should update the first table with the lat/longs from the second, but it's not working:
update t1
set t1.MeasurementLat = t2.Latitude,
t1.MeasurementLong = t2.Longitude
from [dbo].[Measurements] as t1
inner join [dbo].[StationCoords] as t2 on t1.StationName like t2.Station
I think there is a problem with the way the station name is being read, and perhaps something to do with encoding, because this query brings back an empty result, too:
SELECT TOP (5) *
FROM [dbo].[Measurements]
WHERE [StationName] = 'אריאל מכללה';
Any ideas?
Your example names are not the same. Perhaps this will work:
update m
set MeasurementLat = sc.Latitude,
MeasurementLong = sc.Longitude
from dbo.[Measurements] m join
dbo.[StationCoords] sc
on m.StationName like sc.Station + '%';

Totalling up values across salesforce account hierarchies

I'm struggling to find an approach to the following problem, can anyone suggest a high level approach.
Using talend, I have an input set of values for a set of accounts (from CSV):
AccountId, ValueXYZ__c
I want to store ValueXYZ against the SFDC account, which is no problem, but then I want to totalise ValueXYZ up for all the accounts with the same parent to
Account.Parent.TotalValueXYZ
I then want to "roll" this all the way up the accounts hierarchy:
Imagine account hierarchy:
A
-B
--C
--D
-E
--F
--G
I want 3 values on A:
ValueXYZ = account A's ValueXYZ
TotalValueXYZ = total of ValueXYZ values for all accounts under A in the hierarchy
TOTAL = formula field to add together the previous 2 values
I want 3 values on account B
ValueXYZ = account B's ValueXYZ
TotalValueXYZ = total of ValueXYZ values for accounts C & D
TOTAL = formula field to add together the previous 2 values
I want 3 values on account C
ValueXYZ = account C's ValueXYZ
TotalValueXYZ = 0
TOTAL = formula field to add together the previous 2 values
I've tried several approaches, but can't get any of them to work!
Where is the hierarchy information stored? If you can flatten the hierarchy information in a key-value pair format, then it is straightforward. Just read your input file and do a lookup/join on the hierarchy file. You will have to loop through until you get to the base record
The crux of my problem was in not knowing each accounts position in a hierarchy. Once I had that in place, I could loop from the lowest level to the highest level, totalling these values up to their parents.
Here is the T-SQL I wrote to mark each account with it's Hierarchy Position (HILEVEL)
TRUNCATE TABLE [TALEND_WORKSPACE].[dbo].[SFDCAccount]
INSERT INTO [TALEND_WORKSPACE].[dbo].[SFDCAccount] (Id, ParentId, QCIYTDOneTime, QCIYTDRecurring, HILEVEL)
SELECT Id, ParentId, ValueXYZ, '0'
FROM [TALEND_WORKSPACE].[dbo].[SFDCAccountRawData]
WHERE ParentId = ' ';
USE TALEND_WORKSPACE
IF OBJECT_ID('dbo.sfdcaccounthierarchy', 'P') IS NOT NULL
DROP PROCEDURE [dbo].[sfdcaccounthierarchy];
GO
CREATE PROCEDURE [dbo].[sfdcaccounthierarchy]
AS
DECLARE #v_counter int;
DECLARE #v_lastccounter int;
DECLARE #v_max int;
SET #v_counter = 0;
SET #v_lastccounter = 0;
SET #v_max = 10;
WHILE (#v_counter < #v_max)
BEGIN
SET #v_lastccounter = #v_counter;
SET #v_counter = #v_counter+1;
PRINT #v_counter;
INSERT INTO [dbo].[SFDCAccount] (Id, ParentId, QCIYTDOneTime, QCIYTDRecurring, HILEVEL)
SELECT Id, ParentId, ValueXYZ, #v_counter
FROM [TALEND_WORKSPACE].[dbo].[SFDCAccountRawData]
WHERE ParentId IN (SELECT Id FROM [TALEND_WORKSPACE].[dbo].[SFDCAccount]
WHERE HILEVEL = #v_lastccounter);
if ##ROWCOUNT != 0
BREAK;
END
GO
EXEC [TALEND_WORKSPACE].[dbo].[sfdcaccounthierarchy];

Need to eliminate the last 4 characters in a string(varchar)

i am using a stored procedure, where it is taking policy number as parameter which is varchar. I need to eliminate the last 4 characters of the policy number when we retrive from the tables. But the data for policy numbers is not consistent, so I am confused how to use the logic for this. The sample policy numbers are:
KSDRE0021-000
APDRE-10-21-000
KSDRE0021
APDRE-10-21
These are four formats where policies are there in our tables.For some policies there is no tailing end '-000', so that is the challenging part. Now, I need to eliminate the tailing part '-000' from the policies when I retrieve the data from tables.
This is the sample code, which is pulling the policy data from tables.
Create Proc usp.dbo.policydataSP #policy_num varchar(18)
AS
Begin
Select * from policy_table pt
where pt.policy_num = #policy_num
End
STEP 1: Create a User Defined Function to normalize a policy number.
create function dbo.normalize_policy_num
(#policy_num varchar(100))
returns varchar(100)
as
begin
-- replace trailing digits
if (#policy_num like '%-[0-9][0-9][0-9]')
set #policy_num = left(#policy_num, len(#policy_num) - 4)
-- replace remaining hyphens
set #policy_num = replace(#policy_num, '-', '')
return #policy_num
end
What this essentially doing is stripping off the trailing '-000' from policy numbers that contain the pattern, then removing remaining hyphens. This function seems to work on your supplied policy numbers:
-- returns: KSDRE0021
select dbo.normalize_policy_num('KSDRE0021-000')
-- returns: APDRE1021
select dbo.normalize_policy_num('APDRE-10-21-000')
-- returns: KSDRE0021
select dbo.normalize_policy_num('KSDRE0021')
-- returns: APDRE1021
select dbo.normalize_policy_num('APDRE-10-21')
STEP 2: Modify your SP as follows:
create proc usp.dbo.policydataSP
#policy_num varchar(18)
as
begin
select
dbo.normalize_policy_num(pt.policy_num) as normalized_policy_num,
pt.*
from policy_table pt
where dbo.normalize_policy_num(#policy_num) = dbo.normalize_policy_num(pt.policy_num)
Note: If you are able to modify the table schema, you could add a persisted computed column using the UDF specified above. If you add an index to it, queries will run much faster. However, there will be some penalty for inserts, so there is a trade-off.
this is probably your best bet. Match the policy number up to the length of the requested parameter:
Create Proc usp.dbo.policydataSP
#policy_num varchar(18)
AS
Begin
Select * from policy_table pt where LEFT(len(#policy_num),pt.policy_num) = #policy_num
End
If you only want to strip -000 when returning results:
select case right(policy_num, 4)
when '-000' then left(policy_num, len(policy_num) - 4)
else policy_num end as policy_num
from policy_table pt
where pt.policy_num = #policy_num
If you want to strip any 3-digit value following a dash:
select case when policy_num like '%-[0-9][0-9][0-9]' then left(policy_num, len(policy_num) - 4)
else policy_num end as policy_num
from policy_table pt
where pt.policy_num = #policy_num

Only the last entry is selected to itab

At my selection Screen you can choose with a radio button Group with which kind of number you want to select the information. (material number, construction contract or customer order).
After choosing a kind, the User have to fill in the number(s) into the corresponding select option.
With this information I select the information I need an move them to the itab t_marc. This table has the same fields as marc.
When the User choose material number at the selection screen everything works fine and the values to every number the user wrote down is displayed at the ALV-List.
When selecting by one of the other numbers, the values in output are also right, but only the information to the last denoted number will be edited.
How can I move all numbers to my itabs?
PARAMETERS: p_mat RADIOBUTTON GROUP radi.
PARAMETERS: p_auf RADIOBUTTON GROUP radi.
PARAMETERS: p_vbl RADIOBUTTON GROUP radi.
SELECT-OPTIONS: s_matnr FOR marc-matnr.
SELECT-OPTIONS: s_aufnr FOR aufk-aufnr.
SELECT-OPTIONS: s_vbeln FOR vbap-vbeln.
start-of-selection
IF p_mat = 'X'.
SELECT * FROM marc
INTO TABLE t_marc
WHERE matnr IN s_matnr
AND werks = p_werks.
ELSEIF p_auf = 'X'.
SELECT * FROM afpo
INTO TABLE t_afpo
WHERE aufnr IN s_aufnr.
LOOP AT t_afpo.
SELECT * FROM marc
INTO TABLE t_marc
WHERE matnr = t_afpo-matnr
AND werks = p_werks.
ENDLOOP.
ELSEIF p_vbl = 'X'.
SELECT * FROM vbap
INTO TABLE t_vbap
WHERE vbeln = s_vbeln-low
AND posnr IN s_posnr.
LOOP AT t_vbap.
SELECT * FROM marc
INTO TABLE t_marc
WHERE matnr = t_vbap-matnr
AND werks = p_werks.
ENDLOOP.
You're overwriting the records every time in this loop (and the similar loops).
LOOP AT t_afpo.
SELECT * FROM marc
INTO TABLE t_marc
WHERE matnr = t_afpo-matnr
AND werks = p_werks.
ENDLOOP.
"INTO TABLE" overwrites every time. You could switch to "APPENDING TABLE." Alternatively, I would use a for all entries select instead (no loop).
SELECT * FROM marc
INTO TABLE t_marc
FOR ALL ENTRIES IN t_afpo
WHERE matnr = t_afpo-matnr
AND werks = p_werks.
Always make sure there are records in the driver table (in this case, t_afpo) or you will have performance issues.

Resources