Insert selected values - sql

Have table users with vallues :
FirstName LastName Age
A A 20
B B 21
C C 22
D D 21
E E 20
Have procedure where I select values from this table , then want sorting and insert to another tables, I do it like :
SELECT #firstName = FirstName ,lastName = LastName ,#age = Age FROM dbo.users
if #age = 20
insert into tbl1(FirstName,LastName) values (#firstName,#LastName )
if #age = 21
insert into tbl2(FirstName,LastName) values (#firstName,#LastName )
if #age = 22
insert into tbl3(FirstName,LastName) values (#firstName,#LastName )
When I do like this ,all rows dont insert to tables, i think need loop or something for do it, can anyone help me ? I want do it without cursor

Wrap these codes inside your procedure.
insert into tbl1(FirstName,LastName) SELECT FirstName ,LastName FROM dbo.users WHERE Age = 20;
insert into tbl2(FirstName,LastName) SELECT FirstName ,LastName FROM dbo.users WHERE Age = 21;
insert into tbl3(FirstName,LastName) SELECT FirstName ,LastName FROM dbo.users WHERE Age = 22;

begin tran
declare #firstName varchar(20)
declare #lastName varchar(20)
declare #age int
SELECT #firstName = firstName,
#lastName = lastName,
#age = Age
FROM dbo.users
if #age = 20
begin
insert into tbl1
select #firstName,#LastName from dbo.users where #age = 20
end
if #age = 21
begin
insert into tbl2
select #firstName,#LastName from dbo.users where #age = 21
end
if #age = 22
begin
insert into tbl3
select #firstName,#LastName from dbo.users where #age = 22
end
--check
select * from tbl1
select * from tbl2
select * from tbl3
rollback tran
--commit tran

Related

How To Filter SQL Results Efficiently

I have a requirement to filter the table records based on passed input criteria to the SQL stored procedure. To make it simple, I'm elaborating the question using simple Employee table (I'm using MSSQL server for my project):
Table: Employee(Id, FirstName,LastName, Designation)
The stored procedure takes 3 input arguments (Id, LastName, Designation). This will be invoked with at-least one input parameter (other parameter will be set to empty string (in case of LastName, Designation) or 0 (In case of Id)).
Here is the stored procedure:
Create Procedure GetEmployees
(
#id int,
#lastName varchar(30),
#designation varchar(30)
)
AS
BEGIN
Create Table #employees (Id int, FirstName varchar(30),LastName varchar(30), Designation varchar(30);
IF(#id != 0)
BEGIN
Insert Into #employees (Id,FirstName,LastName,Designation)
Select Id, FirstName,LastName,Designation From Employee Where Id = #id
END
IF(#lastName != ‘’)
BEGIN
Insert Into #employees (Id,FirstName,LastName,Designation)
Select Id, FirstName,LastName,Designation From Employee Where LastName = #lastName
END
IF(designation != ‘’)
BEGIN
Insert Into #employees (Id,FirstName,LastName,Designation)
Select Id, FirstName,LastName,Designation From Employee Where Designation = #designation
END
-- Returning filtered record set to the application layer
Select Id,FirstName,LastName,Designation From #employees;
END
GO
I think there a lot of code repetition in the stored procedure. Is there an efficient way of solving this scenario ?
You may use a single insert query with a WHERE clause which covers all the logic:
BEGIN
INSERT INTO #employees (Id, FirstName, LastName, Designation)
SELECT Id, FirstName, LastName, Designation
FROM Employee
WHERE
(Id = #id AND #id <> 0) OR
(LastName = #lastName AND #lastName <> '') OR
(Designation = #designation AND #designation <> '');
You can use Case condition in Where clause, Find Below Query.
INSERT INTO #employees (Id, FirstName, LastName, Designation)
SELECT Id, FirstName, LastName, Designation
FROM Employee
WHERE
(Id = CASE WHEN #id = 0 THEN ID ELSE #ID END) OR
(LastName = CASE WHEN #lastName = '' THEN LastName ELSE #lastName END) OR
(Designation = CASE WHEN #designation = '' THEN Designation ELSe #designation END);
We can also Use AND Instead of OR in Where clause.
As #trincot said, there is no need for a temporary table. My suggestion is:
Create Procedure GetEmployees
(
#id int,
#lastName varchar(30),
#designation varchar(30)
)
AS
BEGIN
Select Id, FirstName,LastName,Designation From Employee
Where (#id>'' AND Id = #id)
OR (#lastName>'' AND LastName = #lastName)
OR (#designation>'' AND Designation = #designation);
END
GO

How to write dynamic insert statement in sql server?

I have a Student table and Department table.
Student Table contains Three columns
StudentId | DeptId | StudentName
Department Table contains
DeptId | DeptName
It may be the case that DeptTable sometimes doesnot exists. That is I am deploying script with two scenarios sometimes with department and sometimes without. In the case without department , departmentId will not be there in student table
So when Department table exists I have to insert value of DeptId otherwise I have to write insert statement without departmentId
IF (EXISTS(
SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'Department'
AND column_name = 'DeptId'
))
DECLARE #DeptId UNIQUEIDENTIFIER;
SET #DeptId = Select DeptId From Department Where DeptName = 'Computer'
INSERT INTO Student ([DeptId], [StudentName])
VALUES (#DeptId, 'TBAG')
But as DeptId column sometimes not present I need to create dynamic Sql.
So I created Select statement
DECLARE #sqlCommand nvarchar(1000)
DECLARE #DeptName varchar(75)
declare #DeptId uniqueIdentifier
SET #DeptName = 'Computer'
SET #sqlCommand = 'SELECT #dept=DeptId FROM customers WHERE DeptName = #DeptName'
EXECUTE sp_executesql #sqlCommand, N'#DeptName varchar(50),#dept uniqueIdentifier OUTPUT', #DeptName = #DeptName, #dept=#DeptId OUTPUT
But how to write Insert statement I am not getting
CREATE TABLE dbo.Student
(
DeptId UNIQUEIDENTIFIER,
StudentName VARCHAR(20)
)
GO
DECLARE #DeptId UNIQUEIDENTIFIER
IF COL_LENGTH('dbo.Department', 'DeptId') IS NOT NULL BEGIN
SELECT #DeptId = DeptId
FROM dbo.Department
WHERE DeptName = 'Computer'
END
INSERT INTO dbo.Student(DeptId, StudentName)
SELECT #DeptId /* null is when DeptId is not exists */, 'TBAG'
Output -
(1 row(s) affected)
As per my understanding you want to prepare dynamic insert statement for student table with two cases (with deptid or without deptid)
Please refer the code below.
DECLARE #STUDENTID INT='',--MENTION YOUR STUDENT ID VALUE AND USE THE SAME IN THE ELSE PART COMMENT OUT IF IT HAS IDENTITY
#STUDENTNAME VARCHAR(100)=''--MENTION YOUR STUDENT NAME
IF Col_length('dbo.Student', 'DeptId') IS NOT NULL
BEGIN
INSERT INTO dbo.Student
(DeptId,
StudentName)
SELECT DeptId,
'TBAG'
FROM dbo.Department
WHERE DeptName = 'Computer'
END
ELSE
BEGIN
INSERT INTO dbo.Student
(StudentName)
SELECT #STUDENTNAME
END

How can I insert the results of a stored procedure into a new table

ALTER procedure [dbo].[staffscorecard]
#STAFF_ID INT = NULL
as
select
count(STAFF_ID) as countexel
from
TbStudentSurvey
where
FEEDBACK = 'excellent'
and STAFF_ID = ISNULL(#STAFF_ID, STAFF_ID)
select
Score as scoreexel
from
TbStaffScoreMaster
where
Status = 'Excellent'
exec [dbo].[staffscorecard]
GO
CREATE TABLE #temp ( countexel int, scoreexel int)
GO
INSERT INTO #temp (countexel , scoreexel)
EXEC [dbo].[staffscorecard]
GO
SELECT *
FROM #temp
GO
For a given staffid to calculate countexel and scoreexel you can re-write your stored procedure as:
create table TbStudentSurvey (STAFF_ID int,FEEDBACK varchar(20));
insert into TbStudentSurvey values (1,'excellent'),(1,'excellent'),(2,'excellent');
create table TbStaffScoreMaster (Score int,[Status] varchar(20));
insert into TbStaffScoreMaster values(100,'Excellent');
Go
create procedure [dbo].[staffscorecard]
#STAFF_ID INT = NULL,
#countexel int output,-- Explicitly declare output variables to fetch these values
#scoreexel int output
as
Begin
select
#countexel = count(STAFF_ID)
from
TbStudentSurvey
where
FEEDBACK = 'excellent'
and STAFF_ID = ISNULL(#STAFF_ID, STAFF_ID)
select
#scoreexel = Score
from
TbStaffScoreMaster
where
Status = 'Excellent'
End
GO
and then instead of using a temp table use a table variable because when you use temp tables,the table has to match the exact column layout as of the stored procedure.
--CREATE TABLE #temp (countexel int, scoreexel int)
--GO
--Create a table variable:
declare #temp table (countexel int, scoreexel int)
declare #countexel int, #scoreexel int,#STAFF_ID int;
--set value of staff Id for which you want to get countexel and scoreexel.
set #STAFF_ID = 1;
EXEC [dbo].[staffscorecard] #STAFF_ID ,#countexel output,#scoreexel output
INSERT #temp values (#countexel ,#scoreexel);
SELECT *
FROM #temp
GO
Method 2:
You can also write as:
alter procedure [dbo].[staffscorecard]
#STAFF_ID INT = NULL
as
Begin
select
count(STAFF_ID) as countexel , Score as scoreexel
from
TbStudentSurvey TSS
inner join TbStaffScoreMaster TSM on TSM.Status = TSS.FEEDBACK
where
FEEDBACK = 'excellent'
and STAFF_ID = ISNULL(#STAFF_ID, STAFF_ID)
group by STAFF_ID,Score
End
GO
declare #temp table (countexel int, scoreexel int)
declare #STAFF_ID int;
set #STAFF_ID = 1;--set value of staff Id for which you want to get countexel and scoreexel.
INSERT #temp EXEC [dbo].[staffscorecard] #STAFF_ID
SELECT *
FROM #temp
GO
Hope this helps!!

Multiple joins, show one value if it occurs more than once

Say I have 3 tables below:
Table1 t1
id c1 c2
1 Jon Doe
2 James SMith
3 jolly rancher
Table2 t2
id c1
1 addr_1
1 addr_2
2 addr_1
2 addr_2
3 addr_1
Table3 t3
id c1
1 phone_1
2 phone_1
3 phone_1
3 phone_2
What i am trying to get is this:
1 Jon Doe addr_1 phone_1
1 addr_2
2 James SMith addr_1 phone_1
2 addr_2
3 jolly rancher addr_1 phone_1
3 phone_2
So that id is there for each output but other fields only once per that grouping—is this possible?
Is it possible? Yes. Is it ideal? Not really. I have to agree with D Stanley that it is definitely better to handle something like this in the app/reporting layer if you can.
However, if you really wanted to do this in SQL, you can see my solution below or go to the SQL fiddle here. This solution is not ideal because it's only working off the sample data you provided. If you have data where there are at least 2 phone numbers and at least 2 addresses for a given person, then the SQL below would need to be modified to handle that scenario. I've renamed the tables and columns to something a little more meaningful so that it's easier to read.
create table person(
id int,
firstName varchar(20),
lastName varchar(20)
)
create table address(
id int,
addr varchar(20)
)
create table phonenumber(
id int,
phoneNum varchar(20)
)
insert person (id, firstName, lastName)select 1, 'jon', 'doe'
insert person (id, firstName, lastName)select 2, 'james', 'smith'
insert person (id, firstName, lastName)select 3, 'jolly', 'rancher'
insert address(id, addr)select 1, 'addr_1'
insert address(id, addr)select 1, 'addr_2'
insert address(id, addr)select 2, 'addr_1'
insert address(id, addr)select 2, 'addr_2'
insert address(id, addr)select 3, 'addr_1'
insert phonenumber(id, phoneNum)select 1, 'phone_1'
insert phonenumber(id, phoneNum)select 2, 'phone_1'
insert phonenumber(id, phoneNum)select 3, 'phone_1'
insert phonenumber(id, phoneNum)select 3, 'phone_2'
CREATE TABLE #results(
id int,
firstName varchar(20),
lastName varchar(20),
address varchar(20),
phoneNumber varchar(20)
)
CREATE TABLE #finalresults(
id int,
firstName varchar(20),
lastName varchar(20),
address varchar(20),
phoneNumber varchar(20)
)
INSERT #results
(
id, firstName, lastName, address, phoneNumber
)
SELECT Person.id, Person.firstName, Person.lastName, address.addr, phonenumber.phoneNum
FROM Person
INNER JOIN address
ON person.id = address.id
INNER JOIN phonenumber
ON person.id = phonenumber.id
DECLARE #id int, #firstname varchar(20), #lastname varchar(20),
#address varchar(20), #phonenumber varchar(20)
DECLARE my_cursor CURSOR
FOR SELECT * FROM #results
OPEN my_cursor
FETCH NEXT FROM my_cursor INTO #id, #firstname, #lastname, #address, #phonenumber
while ##fetch_status = 0
BEGIN
IF NOT EXISTS (SELECT 1 FROM #finalresults WHERE id = #id)
BEGIN
INSERT #finalresults(id, firstname, lastname, address, phonenumber)
SELECT #id, #firstname, #lastname, #address, #phonenumber
END
ELSE
BEGIN
INSERT #finalresults(id, firstname, lastname, address, phonenumber)
SELECT distinct #id, '', '',
CASE WHEN finalAddress.address IS NOT NULL
THEN ''
ELSE #address
END,
CASE WHEN finalPhoneNumber.phonenumber IS NOT NULL
THEN ''
ELSE #phonenumber
END
FROM #finalresults
LEFT OUTER JOIN #finalresults finalAddress
ON finalAddress.id = #id
AND finalAddress.address = #address
LEFT OUTER JOIN #finalresults finalPhoneNumber
ON finalPhoneNumber.id = #id
AND finalPhoneNumber.phonenumber = #phonenumber
END
FETCH NEXT FROM my_cursor INTO #id, #firstname, #lastname, #address, #phonenumber
END
CLOSE my_cursor
DEALLOCATE my_cursor
SELECT * FROM #finalresults

inner join to table depend on values in first table column join second or third table

I have four tables User,Destination,City and visited
as follows
declare #user table
(
UserId int identity(1,1) not null ,
UserName nvarchar(500)
)
insert into #user (UserName) values ('rahul')
insert into #user (UserName) values ('nitin')
insert into #user (UserName) values ('yunus')
declare #destination table
(
destCode nvarchar(50),
destName nvarchar(500)
)
insert into #destination select 'SWDP','ranthambore national park '
insert into #destination select 'BTP','ghana national park '
declare #city table
(
cityId int identity(1,1) not null,
cityname nvarchar(500)
)
insert into #city select 'jaipur'
insert into #city select 'delhi'
-- visited table in which user id with either destCode or cityId
declare #visited table
(
UserId int ,
LocationFrom nvarchar(500),
LocationTo nvarchar(500),
LocType nvarchar(50)
)
insert into #visited select '1','BTP','1','city'
insert into #visited select '1','1','SWDP','dest'
insert into #visited select '2','1','2','city'
insert into #visited select '3','2','SWDP','dest'
insert into #visited select '3','SWDP','BTP','dest'
select * from #user
select * from #destination
select * from #city
select * from #visited
select * from #visited as v
inner join #user as u ON v.UserId=u.UserId
Location type column in visited table denotes the LocationTo type. Its either city or location .
Now i want to join these tables so i can get the data which user started from which city or destination and go to which city and destination .
Expected result is as below image
This is only for one user but i need same for all users .
I am not sure if i understand your table structure correctly
but as i see it the table #destination can be both an origin and an endpoint?
and the LocType only specifies the type of the endpoint (LocationTo in #visited)
Given this i thik you have to assume that a numeric value in #Visited.LocationFrom specifies an Id in #city
then this query might be of use
SELECT u.UserName,
CASE WHEN ISNUMERIC(v.LocationFrom) = 1 THEN (SELECT cityName FROM #city where cityId = cast(v.LocationFrom as int)) ELSE (SELECT destName FROM #destination where destCode = v.LocationFrom) END as LocationFrom,
CASE WHEN ISNUMERIC(v.LocationTo) = 1 THEN (SELECT cityName FROM #city where cityId = cast(v.LocationTo as int)) ELSE (SELECT destName FROM #destination where destCode = v.LocationTo) END as LocationTo
FROM #visited AS v
inner join #user AS u ON v.UserId=u.UserId
This should work for you:
;WITH Locations AS
(SELECT
CAST(CityID as nvarchar(50)) LocationId,
CityName LocationName
FROM
#city
UNION ALL
SELECT
DestCode,
DestName
FROM
#destination)
SELECT
Users.UserName,
LocationsFrom.LocationName LocationFromName,
LocationsTo.LocationName LocationToName
FROM
#visited Visited
INNER JOIN Locations LocationsFrom ON LocationsFrom.LocationID = Visited.LocationFrom
INNER JOIN Locations LocationsTo ON LocationsTo.LocationID = Visited.LocationTo
INNER JOIN #user Users ON Visited.UserID = Users.UserID