How to add a Column to stored procedure result? - sql

I have the following sql procedure:
DECLARE #temp table
(
Column1 nvarchar(1000)
)
INSERT #temp (Column1)
SELECT fld_4
FROM MyTable
WHERE fld_1 = #param1 and
fld_2 = #param2 and
fld_3 = #param3
SELECT ROW_NUMBER() OVER(ORDER BY Column1 ASC) AS Number, Split.a.value('.', 'VARCHAR(100)') AS Result
FROM
(
SELECT Column1,
CAST ('<M>' + REPLACE(Column1, ';', '</M><M>') + '</M>' AS XML) AS Result
FROM #temp
) AS A CROSS APPLY Result.nodes ('/M') AS Split(a);
Structure of MyTable:
| fld_1 | fld_2 | fld_3 | fld_4 | ... | fld_9 | ...|
Where fld_4 contains something like this:
-9;-9;-1;-9;-9;-9;-9;-9;-1;-9;-9;-9;-9;-9;-9;-9;-9;-9;-1;-9;-9;-9;-9;-9;-9;-9;-9;-9;-1;-9;-1;-9;-9;-9;-1;-9;-9;-9;-9;-9;-9;-1;-1;-1;-1;-9;-1;-1;-9;-9;-9;-9;-1;-9;-1;-9;-9;-9;-1;-9;-1;-9;-1;-9;-9;-9;-9;-1;-9;-9;-1;-1;-9;-1;-1;0000;FFF8;-9;-9;-9;-1;-9;-1;-9;FFF6;-9;-1;-9;-1;-9;-1;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9
My procedure returns a table with this structure:
| Number | Result |
| 1 | -9 |
| 2 | -9 |
| 3 | -1 |
| ... | ... |
Now, I want to achieve the following result:
| Number | Result | NewColumn |
| 1 | -9 | Value of fld_9 |
| 2 | -9 | Value of fld_9 |
| 3 | -1 | Value of fld_9 |
| ... | ... | Value of fld_9 |
Any suggestions?

You cannot call a Stored Procedure result directly..
However you can make view or or table-valued user-defined function then get results..
Other way insert Stored Procedure result on TempTable
INSERT INTO #tempTable EXEC MyStoredProcedure
look at this Quick Sample
Create PROCEDURE SampleStoreProc
AS
BEGIN
Select 'Burak', 1
END
GO
Create Table #TempTable
(
MyCol Varchar(50),
ReferanceCol int
)
Insert into #TempTable Exec SampleStoreProc
go
Create Table TestTable2
(
MyCol2 varchar(250),
RefCol int
);
go
Insert into TestTable2 values ('Yeni', 1);
Select a.MyCol, b.MyCol2 From #TempTable a
left join TestTable2 b on b.RefCol = a.ReferanceCol

If I understand what you are asking, you simply want another column included in your result set. Something like the following snippet should work. Keep your FROMclause, and add , MyTable to the end of it.
...
SELECT
ROW_NUMBER() OVER(ORDER BY Column1 ASC) AS Number
, Split.a.value('.', 'VARCHAR(100)') AS Result
, fld_9 AS NewColumn
FROM
...
, MyTable
WHERE
MyTable.fld_1 = #param1 AND
MyTable.fld_2 = #param2 AND
MyTable.fld_3 = #param3;

Related

How to add items from another table based on a string aggregated column

I have 2 tables like this
[Table 1]:
|cust_id| tran |item |
| ------| -----|-------
| id1 | 123 |a,b,c |
| id2 | 234 |b,b |
| id3 | 345 |c,d,a,b|
[Table 2]:
| item. | value |
| ----- | ----- |
| a | 1 |
| b | 2 |
| c | 3 |
| d | 4 |
I want to create a target value by doing a lookup from table 2 in table 1 using big query.
|cust_id| tran.|item |target|
| ------| -----|------|------|
| id1 | 123 |a,b,c | 6
| id2 | 234 |b,b | 4
| id3 | 345 |c,d,a,b| 10
What can I try next?
Consider below simple approach
select *,
( select sum(value)
from unnest(split(item)) item
join table2
using (item)
) target
from table1
if applied to sample data in your question - output is
Try the following:
select t1.cust_id
, t1.tran
, t1.item
, sum(t2.value) as target
from table_1 t1
, UNNEST(split(t1.item ,',')) as item_unnested
LEFT JOIN table_2 t2
on item_unnested=t2.item
group by t1.cust_id
, t1.tran
, t1.item
With your data it gives the following:
Create a center table that splits the item column values on rows and join that table with table2.
Try following
--Cursor is used to split the item data row by row
--#temp is a temporary table
create table #temp (id varchar(10), trans varchar(10), item varchar(10), item1 varchar(10));
DECLARE #item varchar(10);
DECLARE #id varchar(10);
DECLARE #trans varchar(10);
DECLARE item_cusor CURSOR FOR
SELECT *
FROM table1;
OPEN item_cusor
FETCH NEXT FROM item_cusor
INTO #id,#trans,#item
WHILE ##FETCH_STATUS = 0
BEGIN
insert into #temp
SELECT #id,#trans,#item,*
FROM STRING_SPLIT (#item, ',')
FETCH NEXT FROM item_cusor
INTO #id,#trans,#item
END
CLOSE item_cusor;
DEALLOCATE item_cusor;
--select * from temp
select t.id as cust_id, t.trans,t.item , sum(cast(t2.value as int)) as target
from #temp t
JOIN table2 t2
on t.item1=t2.item
group by t.id, t.trans,t.item;
Cursors: https://www.c-sharpcorner.com/article/cursors-in-sql-server/
Temporary tables: https://www.sqlservertutorial.net/sql-server-basics/sql-server-temporary-tables/
String split function: https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql

SQL Concatenate Strings in order of line numbers

I am using SQL Server 2014 Standard.
I have the following query...
SELECT ach.amt, ades.dsline, ades.des
FROM ##ACHTrans ach
LEFT OUTER JOIN apvodes ades on 1=1 and ades.vo_id = ach.vo_id
WHERE ades.voline = '100'
ORDER by ach.apnum, ach.cknum, ach.vo_id, ach.amt desc
Which gives me the results...
+------------+---------------+------------------------------+
| ach.amt | ades.dsline | ades.des |
+------------+---------------+------------------------------+
| 1232.50 | 1 | This is the description for |
| 1232.50 | 2 | The $1,232.50 ACH Amount |
| 245.18 | 1 | This one is for the $245.18 |
| 245.18 | 2 | transactions details |
| 245.18 | 3 | that has four lines of info |
| 245.18 | 4 | in the description. |
| 79.25 | 1 | This $79.25 item has 1 line. |
| 15.00 | 1 | So does this $15.00 one. |
+------------+---------------+------------------------------+
I need a way to snag this info by the ach.amt line, and concatenate the ades.des info for results similar to:
+------------+--------------------------------------------------------------------------------------------------+
| Amount | Description |
+------------+--------------------------------------------------------------------------------------------------+
| 1232.50 | This is the description for The $1,232.50 ACH Amount |
| 245.18 | This one is for the $245.18 transactions details that has four lines of info in the description. |
| 79.25 | This $79.25 item has 1 line. |
| 15.00 | So does this $15.00 one. |
+------------+--------------------------------------------------------------------------------------------------+
This is what string_agg() does:
select ach.amt,
string_agg(des, ',') within group (order by dsline)
from t
group by ach.amt;
Without STRING_AGG you would use for XML PATH like so:
DECLARE #table TABLE (amt MONEY, dsline INT, [des] VARCHAR(1000));
INSERT #table VALUES
(1232.50,1,'This is the description for'),
(1232.50,2,'The $1,232.50 ACH Amount'),
( 245.18,1,'This one is for the $245.18'),
( 245.18,2,'transactions details'),
( 245.18,3,'that has four lines of info'),
( 245.18,4,'in the description.'),
( 79.25,1,'This $79.25 item has 1 line.'),
( 15.00,1,'So does this $15.00 one.');
SELECT
amt,
[Description] =
(
SELECT t2.[des]+''
FROM #table AS t2
WHERE t.amt = t2.amt
ORDER BY t2.dsline
FOR XML PATH('')
)
-- string_agg(des, ',') within group (order by dsline)
FROM #table AS t
GROUP BY amt;
Results:
amt Description
--------------------- ---------------------------------------------------------------------------------------------
15.00 So does this $15.00 one.
79.25 This $79.25 item has 1 line.
245.18 This one is for the $245.18transactions detailsthat has four lines of infoin the description.
1232.50 This is the description forThe $1,232.50 ACH Amount
This may not be the prettiest solution but I have had to deal with something similar and used a cursor to concatenate my strings in a temporary table and then used that in my final join statement back to the original table. I used table variables so you can play with it yourself.
Following is a code example you can play with:
declare #tableAmt table (
IDNum int,
Amt Money
)
declare #tableDesc table (
IDNum int,
LineNum int,
Info varchar(10)
)
set nocount on
insert #tableAmt (IDNum, Amt)
values (1,100.00),
(2,125.00)
insert #tableDesc (IDNum, LineNum, Info)
values (1,1,'some text'),
(1,2,'more text'),
(2,1,'different'),
(2,2,'text'),
(2,3,'final')
declare #description table
(IDNum int,
ConcatDesc varchar(30)
)
declare #id int,
#oldid int,
#string char(10),
#finalstring varchar(30)
declare getdata_cursor cursor for
select IDNum, Info
from #tableDesc
order by IDNum, LineNum
open getdata_cursor
fetch next from getdata_cursor into
#id, #string
while ##FETCH_STATUS=0
begin
if #oldid <> #id
begin
insert #description(IDNum, ConcatDesc)
values(#oldid, #finalstring)
select #finalstring = ''
end
select #finalstring = isnull(#finalstring,'') + rtrim(#string) + ' '
select #string = '', #oldid = #id
fetch next from getdata_cursor into
#id, #string
end
insert #description(IDNum, ConcatDesc)
values(#oldid, #finalstring)
close getdata_cursor
deallocate getdata_cursor
select ta.IDNum, Amt, ConcatDesc from #tableAmt ta join #description d
on ta.IDNum = d.IDNum

How can I do something like "STRING_AGG" in Sql Server Compact?

everybody
I want to make something like STRING_AGG in Sql Server Compact.
For example, I want to flatten the code column in the table below:
+----+--------+
| Id | Code |
+----+--------+
| 1 | 256987 |
| 1 | 256985 |
| 1 | 356994 |
+----+--------+
So I will get something like that:
+----+------------------------+
| Id | Codes |
+----+------------------------+
| 1 | 256987, 256985, 356994 |
+----+------------------------+
Thanks in advance!
Your best bet will be to do it using C# (string.Join).
There a couple of ways to do this:
1: Using COALESCE
DECLARE #Tbl TABLE
(
Name VARCHAR(20)
);
INSERT INTO #Tbl VALUES
('Jim'),
('Tim'),
('Kim');
DECLARE #ReturnVar VARCHAR(256);
SELECT *
FROM #Tbl;
SELECT #ReturnVar = COALESCE(#ReturnVar + ', ', '') + Name
FROM #Tbl;
SELECT #ReturnVar;
2: Using XML
DECLARE #Tbl TABLE
(
Name VARCHAR(20)
);
INSERT INTO #Tbl VALUES
('Jim'),
('Tim'),
('Kim');
DECLARE #ReturnVar VARCHAR(256);
SELECT STUFF((SELECT ',' + Name
FROM #Tbl
FOR XML PATH('')),1,1,'') AS Name;
You can find a bit more detail here.

MS SQL Group rows based on start and end

I have a table that looks like this with repeating rows of 3 and 3...
Column1 | Column2
CustomerID | 22
CustomerName | ”ABC”
Responsible | ”Allan”
CustomerID | 23
CustomerName | ”DEF”
Responsible | ”Jessica”
CustomerID | 24
CustomerName | ”GHI”
Responsible | ”Paul”
The following script can be used to create the table and populate it with sample data...
CREATE TABLE Responsible
( [ RowType ] VARCHAR(12),
[ Value ] VARCHAR(9) )
;
INSERT INTO Responsible
( [RowType],
[ Value ] )
VALUES
( 'CustomerID',
'22' ),
( 'CustomerName',
'ABC'),
( 'Responsible',
'Allan' ),
( 'CustomerID',
'23' ),
( 'CustomerName',
'DEF' ),
( 'Responsible',
'Jessica' ),
( 'CustomerID',
'24' ),
( 'CustomerName',
'GHI' ),
( 'Responsible',
'Paul' );
And I would like to get it like a table that looks like this:
CustomerID | CustomerName | Responsible
22 | ABC | Allan
23 | DEF | Jessica
24 | GHI | Paul
What is the best way forward?
I got it to work like this in SQL Server. I don't see any other option, but to use a cursor to go down one row at a time. The script below works only in your unique situation.
Create the new table
USE [YOURDATABASE NAME GOES HERE]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Table_2](
[CustomerID] [int] NULL,
[CustomerName] [varchar](50) NULL,
[Responsible] [varchar](50) NULL
) ON [PRIMARY]
GO
Insert Data Into Table
DECLARE #CustomerId INT
DECLARE #CustomerName VARCHAR(50)
DECLARE #Responsible VARCHAR(50)
DECLARE myCursor CURSOR
FOR SELECT Column2 FROM Table_1;
OPEN myCursor;
FETCH NEXT FROM myCursor
INTO #CustomerId;
FETCH NEXT FROM myCursor
INTO #CustomerName;
FETCH NEXT FROM myCursor
INTO #Responsible;
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO [dbo].[Table_2](CustomerID,CustomerName,Responsible)
VALUES (#CustomerId,#CustomerName,#Responsible)
FETCH NEXT FROM myCursor
INTO #CustomerId;
FETCH NEXT FROM myCursor
INTO #CustomerName;
FETCH NEXT FROM myCursor
INTO #Responsible;
END
CLOSE myCursor;
DEALLOCATE myCursor;
GO
edit, SQL server version :
Query 10:
select CustomerID, CustomerName, Responsible
from (
select row_number() over(order by k) as id , v as CustomerID
from t1
where k ='CustomerID') tt1
inner join (
select row_number() over(order by k) as id , v as CustomerName
from t1
where k ='CustomerName') tt2
on tt1.id = tt2.id
inner join (
select row_number() over(order by k) as id , v as Responsible
from t1
where k ='Responsible') tt3
on tt1.id = tt3.id
Results:
| CustomerID | CustomerName | Responsible |
|------------|--------------|-------------|
| 22 | ABC | Allan |
| 23 | DEF | Jessica |
| 24 | GHI | Paul |
This is what you want I think ?
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE t1
(`k` varchar(12), `v` varchar(9))
;
INSERT INTO t1
(`k`, `v`)
VALUES
('CustomerID', '22'),
('CustomerName', 'ABC'),
('Responsible', 'Allan'),
('CustomerID', '23'),
('CustomerName', 'DEF'),
('Responsible', 'Jessica'),
('CustomerID', '24'),
('CustomerName', 'GHI'),
('Responsible', 'Paul')
;
Query 1:
set #v1 = 0, #v2 = 0, #v3 = 0
Query 2:
select CustomerID, CustomerName, Responsible
from (
select #v1:= #v1+1 as id , v as CustomerID
from t1
where k ='CustomerID'
) tt1
inner join (
select #v2:= #v2+1 as id , v as CustomerName
from t1
where k ='CustomerName'
) tt2
on tt1.id = tt2.id
inner join (
select #v3:= #v3+1 as id , v as Responsible
from t1
where k ='Responsible'
) tt3
on tt1.id = tt3.id;
Results:
| CustomerID | CustomerName | Responsible |
|------------|--------------|-------------|
| 22 | ABC | Allan |
| 23 | DEF | Jessica |
| 24 | GHI | Paul |

split the accounid and dbids between braces into two columns

I have a query to split the accounid and dbids between braces separately.
example: [14801].[42]
acid scid
14801 42
but I'm not able to separate after comma ,
example :
[27784].[41],[27781].[41],[27779].[41]
need a query to split this data into rows
you need to create function to split values into rows
create function [dbo].[udf_splitstring] (#tokens varchar(max),
#delimiter varchar(5))
returns #split table (
token varchar(200) not null )
as
begin
declare #list xml
select #list = cast('<a>'
+ replace(#tokens, #delimiter, '</a><a>')
+ '</a>' as xml)
insert into #split
(token)
select ltrim(t.value('.', 'varchar(200)')) as data
from #list.nodes('/a') as x(t)
return
end
select * from into #a udf_splitstring ('[27784].[41],[27781].[41],[27779].[41]',',')
output
[27784].[41]
[27781].[41]
[27779].[41]
coming result store in one temp table
SELECT TOKEN,REPLACE(REPLACE(SUBSTRING(TOKEN,0,CHARINDEX('.',TOKEN)),'[',''),']','') AS first_id
,REPLACE(REPLACE(REVERSE(SUBSTRING(REVERSE(TOKEN),0,CHARINDEX('.',REVERSE(TOKEN)))),'[',''),']','') AS second_id
FROM #a
output
TOKEN first_id second_id
[27784].[41] 27784 41
[27781].[41] 27781 41
[27779].[41] 27779 41
Try this:
DECLARE #START_ID VARCHAR(100)='[27784].[41],[27781].[41],[27779].[41]'
DECLARE #ID VARCHAR(MAX)
DECLARE #COUNT INT
DECLARE #TEMP TABLE(C1 VARCHAR(MAX))
WHILE( CHARINDEX(',',#START_ID))>0
BEGIN
INSERT INTO #TEMP SELECT SUBSTRING(#START_ID,0,CHARINDEX(',',#START_ID))
SET #START_ID=(SELECT REPLACE(#START_ID,(SUBSTRING(#START_ID,0,CHARINDEX(',',#START_ID)+1)),''))
END
INSERT INTO #TEMP SELECT #START_ID
SELECT C1,REPLACE(REPLACE(SUBSTRING(C1,0,CHARINDEX('.',C1)),'[',''),']','') AS SOURCE_ACCOUT_ID
,REPLACE(REPLACE(REVERSE(SUBSTRING(REVERSE(C1),0,CHARINDEX('.',REVERSE(C1)))),'[',''),']','') AS SOURCE_DATABASE_ID
FROM #TEMP
select n.ids.value ('id[1]','int') as accountid
,n.ids.value ('id[2]','int') as dbid
from (select cast (replace('<r><e><id>'+replace(replace(replace(
ids,'[',''),']',''),',','</id></e><e><id>')+
'</id></e></r>','.','</id><id>') as xml) as x
from mytable
) t
cross apply x.nodes ('/r/e') n(ids)
+-----------+------+
| accountid | dbid |
+-----------+------+
| 27784 | 41 |
+-----------+------+
| 27781 | 41 |
+-----------+------+
| 27779 | 41 |
+-----------+------+
| 28021 | 30 |
+-----------+------+
| 28024 | 30 |
+-----------+------+
| 29007 | 56 |
+-----------+------+
DDL + DML for demo
create table mytable (ids varchar(1000))
insert into mytable values
('[27784].[41],[27781].[41],[27779].[41]')
, ('[28021].[30],[28024].[30]')
, ('[29007].[56]')