Query to add up multiple names from TVP - sql-server

I have a table of name value pairs like this
Properties
- EmployeeId
My table for employee looks like this:-
EmployeeId FirstName Middle LastName
1 John Smith
2 Rick Steve James
3 Maddy Y Angela
Now my TVP can contain multiple or single EmployeeId's
I want to add up the full names of all the person in TVP in a single parameter.
i.e.
For eg. If I receive 1 and 3 in TVP
My output should be John Smith, Maddy Y Angela.
Do I need to use cursors in this?
What is the best way to accomplish this?
EDIT
The Scipt For the TVP is as below:-
CREATE TYPE [dbo].[Employee] AS TABLE( [EmployeeId] [uniqueidentifier] NULL)GO
The desired output is the Full Names of Employees in the TVP comma seperated.

Assuming you have a table type like:
CREATE TYPE dbo.TVPTypeName AS TABLE(EmployeeId INT PRIMARY KEY);
Then you can just perform a join:
CREATE PROCEDURE dbo.foo
#bar dbo.TVPTypeName READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT STUFF((SELECT ','
+ e.FirstName
+ COALESCE(' ' + NULLIF(RTRIM(e.Middle),''), ' ')
+ e.LastName
FROM dbo.Employees AS e
INNER JOIN #bar AS b
ON e.EmployeeId = b.EmployeeId
FOR XML PATH(''),TYPE).value('.[1]','nvarchar(max)'),1,1,'');
END
GO

CREATE TYPE dbo.IntArray AS TABLE(IntValue INT PRIMARY KEY);
GO
CREATE TABLE dbo.Employee(
EmployeeID INT IDENTITY(1,1) PRIMARY KEY,
FirstName NVARCHAR(50) NOT NULL,
MiddleName NVARCHAR(50) NULL,
LastName NVARCHAR(50) NOT NULL
);
GO
INSERT INTO dbo.Employee VALUES ('John',NULL,'Smith');
INSERT INTO dbo.Employee VALUES ('Rick','Steve','James');
INSERT INTO dbo.Employee VALUES ('Maddy','Y','Angela');
GO
CREATE PROCEDURE dbo.CocoJambo(#pEmployee dbo.IntArray READONLY)
AS
BEGIN
DECLARE #Result NVARCHAR(MAX);
SELECT #Result=ISNULL(#Result,'')+','+FirstName+ISNULL(' '+MiddleName,'')+' '+LastName
FROM dbo.Employee e INNER JOIN #pEmployee p ON e.EmployeeID=p.IntValue;
SELECT STUFF(#Result,1,1,'') AS [Result];
END;
GO
-- Test
DECLARE #p dbo.IntArray;
INSERT INTO #p VALUES (1);
INSERT INTO #p VALUES (3);
EXEC dbo.CocoJambo #pEmployee=#p;
/*
Result
-------------------------
John Smith,Maddy Y Angela
*/

Related

How do I run through the contents of a MS SQL table and put the rows into a alter table?

I'm looking to run through the contents of a table (MS SQL), collect the names in a column and put them in an alter table loop.
For example:
Bank names(column name) | Desc (column name)
Nationwide | Example
HSBC | Example
Halifax | Example
ALTER TABLE banks
ADD (rows from bank table) varchar(255);
End result:
altered another table:
(Columns within new table \/)
Nationwide | HSBC | Halifax
You can form dynamic sql statements to do this.
--Table to hold the banks while you work
CREATE TABLE #firsttable (Bank VARCHAR(20), Descr VARCHAR(20))
INSERT INTO #firsttable
(
Bank
, Descr
)
VALUES
('Nationwide', 'blah')
, ('HSBC','blah blah')
, ('Halifax', 'blah blah blah')
--The existing table you will be modifying
CREATE TABLE #existingtable (id INT)
--Variables
DECLARE #sql NVARCHAR(MAX)
DECLARE #currentbank VARCHAR(255)
DECLARE #banksleft INT
SELECT #banksleft = COUNT(1) FROM #firsttable;
--Loop through the banks
WHILE (#banksleft > 0)
BEGIN
SELECT #currentbank = bank FROM #firsttable;
SELECT #sql = 'ALTER TABLE #existingtable ADD ' + '[' + #currentbank + '] varchar(255);' FROM #firsttable
--Run the alter statement
EXEC sp_executesql #sql;
--Get rid of the bank you have just added as a column
DELETE
FROM #firsttable WHERE Bank = #currentbank;
--Reset the counter
SELECT #banksleft = COUNT(1) FROM #firsttable;
end
--To show the columns added to the table
SELECT * FROM #existingtable AS e;
--Cleanup
DROP TABLE #firsttable;
DROP TABLE #existingtable;

Inner join in SQL Server based on lookup table

I have the following table structure:
create table table1( ID int,
assettype varchar(50));
create table t1( poolId int,
day_rate float);
create table t2( poolId int,
day_rate float);
create table lookuptable( tablename varchar(50),
assettype varchar(50));
insert into table1 values (1,'abs'), (2,'card');
insert into t1 values ( 1,5), ( 2,10);
insert into t2 values ( 1,15), ( 2,20);
insert into lookuptable values ('t1','abs'), ('t2','card');
SqlFiddle
For a given id based on the assetType field in table1 I need to perform a lookup in the lookup table so that I display if the assettype of the id is abs
poolId day_rate
1 5
2 10
else if the assettype of the id is card
poolId day_rate
1 15
2 20
The reason I have t1 and t2 tables because they have their own set of calculation and based on the asset type of the id i want to use t1 and t2
Would you be able to guide me with some query or steps to go in the right direction
I can think of the case when structure to this but in my case I have 100 entries in the lookuptable and that would mean a case when structure written for 100 times. Is there a better way of handling this?
Try this..
declare #table varchar(20)
select #table=tablename from lookuptable where assettype = 'card'
print #table
declare #query nvarchar(1000)
set #query = N'select * from [' + #table +']';
print #query
EXECUTE sp_executesql #query
Change the assettype in first query..
Are you just trying to get all the rows in table1 and then their day_rates depending on what type of asset they are? Couldn't you do something like this.
select
,table1.ID
,table1.assettype,
,(case when table1.assettype = 'abs' then t1.day_rate else t2.day_rate end) as
day_rate
from table1
inner join t1 on table1.id = t1.poolId
inner join t2 on table1.id = t2.poolId
group by table1.ID, table1.assettype
Let me identify the perspective first.
First, you created this table1 as? well whatever, but this seems a lookup table as well to me.
create table table1(
ID int,
assettype varchar(50)
);
Next, this one is a lookup table as well because this one is your reference for calculation.
create table t1(
poolId int,
day_rate float
);
create table t2(
poolId int,
day_rate float
);
Lastly, is your direct lookup table depending on the assettype defines which table you will get the rate.
create table lookuptable(
tablename varchar(50),
assettype varchar(50)
);
So, i'll try to simplify this.
One is your table1 with an additional column
create table table1(
ID int,
assettype varchar(50),
day_rate float
);
insert into table1 values
(1,'abs',5)
,(2,'card',10)
I have no further reasons yet to split the table as One-To-Many table relationship as I don't see the lookuptable as "child" as well as t1 and t2. You could instead directly change the rates in table1 rate as desired.
Please put some comments so we can arrive at the same page. thanks

Transform row in column in a table

I am trying to rotate the visualization of a table showing the lines as columns without any kind of aggregation.
Suppose I have this table
create table user
id int,
name nvarchar(100),
company nvarchar(100),
division nvarchar(100),
city nvarchar(100)
that can be retrieved with this select
select name,company division, city from user order by id
wich gives me this result
john Company1 division1 City1
Peter Company2 division2 City2
Mary Company3 division3 City3
.
.
but what I need is to show each line as a column and the first column with the name of the field like this
Name john Peter Mary ....
Company Company1 Company2 Company3 ....
Division division1 division2 division3 ....
City City1 City2 City3 ....
How can I accomplish this? I Tried using this unpivot
select col,value
from
(select cast(name as varchar) as name,
cast(Company as varchar) as company,
cast(Division as varchar) as division
cast(City as varchar) as city
from user) p
unpivot
(value for col in (name,company,division,city)) as unpvt
but this is what I got (Note: I want all the names in the same row)
name john
Company Company1
Division division1
City City1
name peter // this should be in the first row as a second column
Company Company2
Division division2
City City2
...
This is super ugly, but it's the only way I could figure out how to do what you want solely in SQL Server. If you copy and paste the code it should run and give you results and leave your database clean. I use a couple permanent tables to work around some dynamic sql scoping limitations, but I drop them both before it's done.
If Object_ID('tempdb..#userInfo') Is Not Null Drop Table #userInfo
Create Table #userInfo (id Int, name Varchar(100), company Varchar(100), division Varchar(100), city Varchar(100))
Insert #userInfo (id, name, company, division, city)
Values (1, 'john','company1', 'division1', 'city1'),
(2, 'peter','company2', 'division2', 'city2'),
(3, 'mary','company3', 'division3', 'city3'),
(4, 'timmy','company4', 'division4', 'city4'),
(5, 'nancy','company5', 'division5', 'city5'),
(6, 'james','company6', 'division6', 'city6'),
(7, 'brandon','company7', 'division7', 'city7'),
(8, 'jay','company8', 'division8', 'city8')
If Object_ID('tempdb..#unPivoted') Is Not Null Drop Table #unPivoted
Create Table #unPivoted (id Int, rid Int, col Varchar(100), value Varchar(100))
Insert #unPivoted
Select id, Row_Number() Over (Partition By id Order By value) As rID, col, value
From #userInfo p
Unpivot (value For col In (name, company, division, city)) As u
If Object_ID('dbo.TempQueryOutput') Is Not Null Drop Table dbo.TempQueryOutput
Select 1 As OrderCol,'City' As ColName Into dbo.TempQueryOutput
Union
Select 2,'Company'
Union
Select 3,'Division'
Union
Select 4,'Name'
Declare #sql Nvarchar(Max),
#maxID Int,
#loopIter Int = 1
Select #maxID = Max(id)
From #userInfo
While #loopIter <= #maxID
Begin
Set #sql = 'Select o.*, u.value As Col' + Convert(Nvarchar(100),#loopIter) + ' Into dbo.TempQueryTable
From dbo.TempQueryOutput o
Join #unPivoted u
On o.OrderCol = u.rid
And u.id = ' + Convert(Nvarchar(100),#loopIter)
Exec sp_executeSQL #sql
If Object_ID('dbo.TempQueryOutput') Is Not Null Drop Table dbo.TempQueryOutput
Select * Into dbo.TempQueryOutput
From dbo.TempQueryTable
If Object_ID('dbo.TempQueryTable') Is Not Null Drop Table dbo.TempQueryTable
Set #loopIter = #loopIter + 1
End
Update dbo.TempQueryOutput
Set OrderCol = Case
When ColName = 'Name' Then 1
When ColName = 'Company' Then 2
When ColName = 'Division' Then 3
When ColName = 'City' Then 4
End
Select *
From dbo.TempQueryOutput
Order By OrderCol
If Object_ID('dbo.TempQueryOutput') Is Not Null Drop Table dbo.TempQueryOutput

Inserting batch of rows into two tables in SQL Server 2008

I have a requirement to insert multiple rows into table1 and at the same time insert a row into table2 with a pkID from table1 and a value that comes from a SP parameter.
I created a stored procedure that performs a batch insert with a table valued parameter which contains the rows to be inserted into table1. But I have a problem with inserting the row into table2 with the corresponding Id (identity) from table1, along with parameter value that I have passed.
Is there anyone who implemented this, or what is the good solution for this?
CREATE PROCEDURE [dbo].[oSP_TV_Insert]
#uID int
,#IsActive int
,#Type int -- i need to insert this in table 2
,#dTableGroup table1 READONLY -- this one is a table valued
AS
DECLARE #SQL varchar(2000)
DECLARE #table1Id int
BEGIN
INSERT INTO dbo.table1
(uID
,Name
,Contact
,Address
,City
,State
,Zip
,Phone
,Active)
SELECT
#uID
,Name
,Contact
,Address
,City
,State
,Zip
,Phone
,Active
,#G_Active
FROM #dTableGroup
--the above query will perform batch insert using the records from dTableGroup which is table valued
SET #table1ID = SCOPE_IDENTITY()
-- this below will perform inserting records to table2 with every Id inserted in table1.
Insert into table2(#table1ID , #type)
You need to temporarily store the inserted identity values and then create a second INSERT statement - using the OUTPUT clause.
Something like:
-- declare table variable to hold the ID's that are being inserted
DECLARE #InsertedIDs TABLE (ID INT)
-- insert values into table1 - output the inserted ID's into #InsertedIDs
INSERT INTO dbo.table1(ID, Name, Contact, Address, City, State, Zip, Phone, Active)
OUTPUT INSERTED.ID INTO #InsertedIDs
SELECT
#ID, Name, Contact, Address, City, State, Zip, Phone, Active, #G_Active
FROM #dTableGroup
and then you can have your second INSERT statement:
INSERT INTO dbo.table2(Table1ID, Type)
SELECT ID, #type FROM #InsertedIDs
See the MSDN docs on the OUTPUT clause for more details on what you can do with the OUTPUT clause - one of the most underused and most "unknown" features of SQL Server these days!
Another approach using OUTPUT clause and only one statement for inserting data in both destination tables:
--Parameters
DECLARE #TableGroup TABLE
(
Name NVARCHAR(100) NOT NULL
,Phone VARCHAR(10) NOT NULL
);
DECLARE #Type INT;
--End Of parameters
--Destination tables
DECLARE #FirstDestinationTable TABLE
(
FirstDestinationTableID INT IDENTITY(1,1) PRIMARY KEY
,Name NVARCHAR(100) NOT NULL
,Phone VARCHAR(10) NOT NULL
);
DECLARE #SecondDestinationTable TABLE
(
SecondDestinationTable INT IDENTITY(2,2) PRIMARY KEY
,FirstDestinationTableID INT NOT NULL
,[Type] INT NOT NULL
,CHECK([Type] > 0)
);
--End of destination tables
--Test1
--initialization
INSERT #TableGroup
VALUES ('Bogdan SAHLEAN', '0721200300')
,('Ion Ionescu', '0211002003')
,('Vasile Vasilescu', '0745600800');
SET #Type = 9;
--execution
INSERT #SecondDestinationTable (FirstDestinationTableID, [Type])
SELECT FirstINS.FirstDestinationTableID, #Type
FROM
(
INSERT #FirstDestinationTable (Name, Phone)
OUTPUT inserted.FirstDestinationTableID
SELECT tg.Name, tg.Phone
FROM #TableGroup tg
) FirstINS
--check records
SELECT *
FROM #FirstDestinationTable;
SELECT *
FROM #SecondDestinationTable;
--End of test1
--Test2
--initialization
DELETE #TableGroup;
DELETE #FirstDestinationTable;
DELETE #SecondDestinationTable;
INSERT #TableGroup
VALUES ('Ion Ionescu', '0210000000')
,('Vasile Vasilescu', '0745000000');
SET #Type = 0; --Wrong value
--execution
INSERT #SecondDestinationTable (FirstDestinationTableID, [Type])
SELECT FirstINS.FirstDestinationTableID, #Type
FROM
(
INSERT #FirstDestinationTable (Name, Phone)
OUTPUT inserted.FirstDestinationTableID
SELECT tg.Name, tg.Phone
FROM #TableGroup tg
) FirstINS
--check records
DECLARE #rc1 INT, #rc2 INT;
SELECT *
FROM #FirstDestinationTable;
SET #rc1 = ##ROWCOUNT;
SELECT *
FROM #SecondDestinationTable;
SET #rc2 = ##ROWCOUNT;
RAISERROR('[Test2 results] #FirstDestinationTable: %d rows; ##SecondDestinationTable: %d rows;',1,1,#rc1,#rc2);
--End of test1
Since you need all inserted identity values, look at the output clause of the insert statement: http://msdn.microsoft.com/en-us/library/ms177564.aspx

Best way to get multiple newly created key values from table inserts using SQL Server?

The function Scope_Identity() will provide the last generated primary key value from a table insert. Is there any generally accepted way to get multiple keys from an insertion of a set (an insert resulting from a select query)?
In SQL Server 2005 onwards, you can use the OUTPUT clause to get a returned set of values. From the linked article:
The following example creates the
EmployeeSales table and then inserts
several rows into it using an INSERT
statement with a SELECT statement to
retrieve data from source tables. The
EmployeeSales table contains an
identity column (EmployeeID) and a
computed column (ProjectedSales).
Because these values are generated by
the SQL Server Database Engine during
the insert operation, neither of these
columns can be defined in #MyTableVar.
USE AdventureWorks ;
GO
IF OBJECT_ID ('dbo.EmployeeSales', 'U') IS NOT NULL
DROP TABLE dbo.EmployeeSales;
GO
CREATE TABLE dbo.EmployeeSales
( EmployeeID int IDENTITY (1,5)NOT NULL,
LastName nvarchar(20) NOT NULL,
FirstName nvarchar(20) NOT NULL,
CurrentSales money NOT NULL,
ProjectedSales AS CurrentSales * 1.10
);
GO
DECLARE #MyTableVar table(
LastName nvarchar(20) NOT NULL,
FirstName nvarchar(20) NOT NULL,
CurrentSales money NOT NULL
);
INSERT INTO dbo.EmployeeSales (LastName, FirstName, CurrentSales)
OUTPUT INSERTED.LastName,
INSERTED.FirstName,
INSERTED.CurrentSales
INTO #MyTableVar
SELECT c.LastName, c.FirstName, sp.SalesYTD
FROM HumanResources.Employee AS e
INNER JOIN Sales.SalesPerson AS sp
ON e.EmployeeID = sp.SalesPersonID
INNER JOIN Person.Contact AS c
ON e.ContactID = c.ContactID
WHERE e.EmployeeID LIKE '2%'
ORDER BY c.LastName, c.FirstName;
SELECT LastName, FirstName, CurrentSales
FROM #MyTableVar;
GO
SELECT EmployeeID, LastName, FirstName, CurrentSales, ProjectedSales
FROM dbo.EmployeeSales;
GO
Use the row count and last identity value....
DECLARE #LastID int
DECLARE #Rows int
--your insert from a select here
SELECT #LastID=##IDENTITY, #Rows=##ROWCOUNT
--set of rows you want...
SELECT * FROM YourTable Where TableID>#LastID-#Rows AND TableID<=#LastID

Resources