Here is my table named Employee
-----------------------
Column Name | Data Type
----------------------
ID | int
EmpId | nvarchar
Name | nvarchar
Salary | decimal
Have a look all the records of the table
------------------------------
ID | EmpId | Name | Salary
------------------------------
1 | 200 | Bulbul | 2000.00
2 | 201 | Ahmed | 2000.00
3 | 202 | Rakib | 2500.00
4 | 203 | Rubel | 3000.00
5 | 204 | Zia | 4000.00
Now if I want get all the records of a given employee id to the IN operator, I get the following result. It's just fine.
SELECT EmpId, Name, Salary
FROM Employee
WHERE EmpId IN ('200','201')
------------------------------
ID | EmpId | Name | Salary
------------------------------
1 | 200 | Bulbul | 2000.00
2 | 201 | Ahmed | 2000.00
But if I pass the employee id as parameter, then I don't get my desired results. Just get empty result.
DECLARE #Params AS NVARCHAR(MAX) = '''200'',''201'''
SELECT EmpId, Name, Salary
FROM Employee
WHERE EmpId IN (#Params)
------------------------------
ID | EmpId | Name | Salary
------------------------------
| | |
| | |
Now I need to get the following result using parameter in IN operator. My desired result is something like:
------------------------------
ID | EmpId | Name | Salary
------------------------------
1 | 200 | Bulbul | 2000.00
2 | 201 | Ahmed | 2000.00
Please help me to get my desire result. Thank in advance.
I suggest that use Table Type Parameter.
CREATE TYPE dbo.IdList AS TABLE (Id INT)
GO
DECLARE #Ids dbo.IdList
INSERT INTO #Ids(Id)VALUES(200),(201)
SELECT EmpId, Name, Salary
FROM Employee
WHERE EmpId IN (SELECT Id FROM #Ids)
Add below Table valued SQL Function fn_split:
CREATE FUNCTION [dbo].[fn_Split](#sText varchar(8000), #sDelim varchar(20) = ' ')
RETURNS #retArray TABLE (idx smallint Primary Key, value varchar(8000))
AS
BEGIN
DECLARE #idx smallint,
#value varchar(8000),
#bcontinue bit,
#iStrike smallint,
#iDelimlength tinyint
IF #sDelim = 'Space'
BEGIN
SET #sDelim = ' '
END
SET #idx = 0
SET #sText = LTrim(RTrim(#sText))
SET #iDelimlength = DATALENGTH(#sDelim)
SET #bcontinue = 1
IF NOT ((#iDelimlength = 0) or (#sDelim = 'Empty'))
BEGIN
WHILE #bcontinue = 1
BEGIN
--If you can find the delimiter in the text, retrieve the first element and
--insert it with its index into the return table.
IF CHARINDEX(#sDelim, #sText)>0
BEGIN
SET #value = SUBSTRING(#sText,1, CHARINDEX(#sDelim,#sText)-1)
BEGIN
INSERT #retArray (idx, value)
VALUES (#idx, #value)
END
--Trim the element and its delimiter from the front of the string.
--Increment the index and loop.
SET #iStrike = DATALENGTH(#value) + #iDelimlength
SET #idx = #idx + 1
SET #sText = LTrim(Right(#sText,DATALENGTH(#sText) - #iStrike))
END
ELSE
BEGIN
--If you can’t find the delimiter in the text, #sText is the last value in
--#retArray.
SET #value = #sText
BEGIN
INSERT #retArray (idx, value)
VALUES (#idx, #value)
END
--Exit the WHILE loop.
SET #bcontinue = 0
END
END
END
ELSE
BEGIN
WHILE #bcontinue=1
BEGIN
--If the delimiter is an empty string, check for remaining text
--instead of a delimiter. Insert the first character into the
--retArray table. Trim the character from the front of the string.
--Increment the index and loop.
IF DATALENGTH(#sText)>1
BEGIN
SET #value = SUBSTRING(#sText,1,1)
BEGIN
INSERT #retArray (idx, value)
VALUES (#idx, #value)
END
SET #idx = #idx+1
SET #sText = SUBSTRING(#sText,2,DATALENGTH(#sText)-1)
END
ELSE
BEGIN
--One character remains.
--Insert the character, and exit the WHILE loop.
INSERT #retArray (idx, value)
VALUES (#idx, #sText)
SET #bcontinue = 0
END
END
END
RETURN
END
And execute this query to get your output:
DECLARE #Params AS NVARCHAR(MAX) = '200,201'
SELECT EmployeeId, Name
FROM Employee
WHERE EmployeeId IN (select value from dbo.fn_Split(#Params,','))
Hope this helps!
Please try:
DECLARE #Params AS NVARCHAR(MAX) = '200,201'
exec ('SELECT EmpId, Name, Salary
FROM Employee
WHERE EmpId IN ('+#Params+')')
Finally I got my expected result doing something like:
CREATE TABLE #EmpTable
(
EmpId NVARCHAR (50) NULL
)
GO
DECLARE #Parameter AS NVARCHAR(MAX) = '(''201''),(''202'')'
DECLARE #SQL AS NVARCHAR(MAX) ='INSERT INTO #EmpTable (EmpId)VALUES' + #Parameter
EXEC (#SQL)
GO
SELECT EmpId, Name, Salary
FROM Employee
WHERE EmpId IN (SELECT EmpId FROM #EmpTable)
Related
So I have a DataSet file with some TableAdapters where main query is just a select from all main columns
problem is that I want to make a join so i can get the string value from the parent table but i get incorrect input string format exception when i do this....
this is the adapters
| Inventory | | Employee |
| ID int | | ID int |
| employee int | ----- | Name nvarchar |
| warehouse int |
I tried to do this in a stored procedure and make the join clause
GO
IF OBJECT_ID('dbo.spx_SELECT_InventariosByCustomPaging') IS NOT NULL
DROP PROCEDURE spx_SELECT_InventariosByCustomPaging
GO
CREATE PROCEDURE spx_SELECT_InventariosByCustomPaging
#startIndex int,
#pageSize int
AS
BEGIN
SET NOCOUNT ON
SELECT ID, Name, Warehouse, DataCriacao
FROM (
SELECT InventarioID, xc.Name, xa.Warehouse, DataCriacao, ROW_NUMBER()
OVER(ORDER BY Colaborador DESC) AS rowNumber
FROM Inventory xi
LEFT JOIN Employee xc
ON xc.ID= xi.ID
LEFT JOIN xArmazem xa
ON xa.ArmazemID = xi.Armazem
) AS Inventario
WHERE rowNumber > #startIndex AND
rowNumber <= (#startIndex + #pageSize )
END
How can I get the Name column on Inventory DataTable?
Additional information: Input string was not in a correct format.Couldn't store in Inventory Column. Expected type is Int.
I want to join two tables and combine it into one but problem is one table is in horizontal format other is in vertical
Below are table structures
Table 1 :
EmpID | Code | Name | Fld1 | Fld2 | Fld3 | Fld4
-- |---- | ------| --- | ---- |---- |----
1 | 1008M | ABC | temp1 | temp2 | temp3 | null
2 | 1039E | XYZ | temp1 | null | null | null
3 | 1040E | TYS | null | null | null | temp6
Table 2 :
EmpID | FieldName | Value
-- |---- | ------
1 | FH | 1000
1 | FB | 1220
2 | FHRA | 3000
2 | FB | 3000
3 | FB | 3000
Desired Output :
EmpID | Code | Name | Fld1 | Fld2 | Fld3 | Fld4 | FH | FB | FHRA
-- |---- | ------| --- | ---- |---- |---- | --- |--- | ----
1 | 1008M | ABC | temp1 | temp2 | temp3 | null |1000 |1210| 0
2 | 1039E | XYZ | temp1 | null | null | null |0 |3000| 3000
3 | 1040E | TYS | null | null | null | temp6|0 |3000| 0
I had tried using Pivot query but it is not working as expected.
You have to use dynamic query as below and you can test is by adding more FieldNames
CREATE TABLE #table1(EmpID INT,
Code VARCHAR(20),
Name VARCHAR(20),
Fld1 VARCHAR(20),
Fld2 VARCHAR(20),
Fld3 VARCHAR(20),
Fld4 VARCHAR(20))
INSERT INTO #table1 VALUES
(1, '1008M','ABC','temp1','temp2','temp3',NULL),
(2, '1039E','XYZ','temp1',NULL,NULL,null),
(3, '1040E','TYS',null,NULL,NULL,'temp6')
CREATE TABLE #table2(EmpID INT, FieldName VARCHAR(20), VALUE INT)
INSERT INTO #table2 VALUES
(1,'FH',1000),
(1,'FB',1220),
(2,'FHRA',3000),
(2,'FB',3000),
(3,'FB',3000)
DECLARE #col VARCHAR(MAX)
DECLARE #sql VARCHAR(MAX)
SELECT #col = COALESCE(#col + ', ','') + QUOTENAME(FieldName)
FROM #table2 GROUP BY FieldName
SELECT #col -- This gives: [FB], [FH], [FHRA]
-- Now setting this #col variable in the Dynamic SQL.
SET #sql = '
select EmpID, Code, Name,Fld1,Fld2,Fld3,Fld4, ' + #col + '
from (select a.EmpID, Code, Name,Fld1,Fld2,Fld3,Fld4, b.FieldName, b.value
from #table1 a
join #table2 b on a.empid=b.empid)p
PIVOT(MAX (VALUE) FOR FieldName IN ( ' + #col + ' )
) AS pvt
'
PRINT #sql
EXEC (#sql)
OUTPUT:
EmpID Code Name Fld1 Fld2 Fld3 Fld4 FB FH FHRA
1 1008M ABC temp1 temp2 temp3 NULL 1220 1000 NULL
2 1039E XYZ temp1 NULL NULL NULL 3000 NULL 3000
3 1040E TYS NULL NULL NULL temp6 3000 NULL NULL
try this working fine
;with demo1 as (
select * from Table_1
), a as
(
SELECT *
FROM Table_2
PIVOT(SUM(value)
FOR Fieldname IN (FH, FB,FHRA)) AS PVTTable
)select demo1.EmpID,demo1.Code,demo1.Name,demo1.Fld1,demo1.Fld2,demo1.Fld3,demo1.Fld4,a.FH,a.FB,a.FHRA
from a inner join demo1 on a.EmpID=demo1.EmpID
OutPut:
declare #temp table(empid int,fh int,fb int, fhra int)
insert into #temp
SELECT *
FROM (
SELECT
empid,fieldname as [field],value as val
FROM dbo.emp
) as s
PIVOT
(
min( val)
FOR [field] IN (fh,fb,fhra)
)AS pvt
select * from #temp join table1
Now join temporary table and table 1.
Try this:
select t1.empid,
t1.code,
t1.fld1,
t1.fld2,
t1.fld3,
t1.fld4,
sum(case when t2.fieldname = 'FH' then t2.value else 0 end) FH,
sum(case when t2.fieldname = 'FB' then t2.value else 0 end) FB,
sum(case when t2.fieldname = 'FHRA' then t2.value else 0 end) FHRA
from table1 t1
left outer join table2 t2
on t1.empid = t2.empid
group by t1.empid,
t1.code,
t1.fld1,
t1.fld2,
t1.fld3,
t1.fld4;
I need to use this procedure and when I insert the new employee I need to create EmpID in database like A1001,A1002...
But when I using this procedure it shows error to pass EmpID.
Sql Procedure:
ALTER procedure [dbo].[addemp]
#EmpId nvarchar(10),
#EmpName nvarchar(50),
#EmpAddress nvarchar(50)
as
begin
declare #Totalcount int
declare #Count nvarchar(10)
select #Totalcount=(select COUNT(EmpID) from NewEmp)
if #Totalcount is null
set #Count='A'+CONVERT(nvarchar(10),1001)
else
set #Count='A'+CONVERT(nvarchar(10),1001+(#Totalcount))
insert into NewEmp([EmpId],[EmpName],[EmpAddress]) values (#Count,#EmpName,#EmpAddress)
end
C# Code:-
protected void Button1_Click(object sender, EventArgs e)
{
string cs = ConfigurationManager.ConnectionStrings["Emp"].ConnectionString;
SqlConnection scon = new SqlConnection(cs);
SqlCommand cmd = new SqlCommand("addemp", scon);
cmd.CommandType = CommandType.StoredProcedure;
scon.Open();
cmd.Parameters.AddWithValue("#EmpName",TextBox2.Text);
cmd.Parameters.AddWithValue("#EmpAddress", TextBox3.Text);
cmd.ExecuteNonQuery();
}
As you are not going to use declared parameter #EmpId in SP, so please remove #EmpId parameter from SP
OR
Set default value : #EmpId=''
create procedure [dbo].[addemp]
#EmpId nvarchar(10)='',
#EmpName nvarchar(50)='',
#EmpAddress nvarchar(50)=''
as
begin
declare #Totalcount int
declare #Count nvarchar(10)
select #Totalcount=(select COUNT(EmpID) from NewEmp)
if #Totalcount is null
set #Count='A'+CONVERT(nvarchar(10),1001)
else
set #Count='A'+CONVERT(nvarchar(10),1001+(#Totalcount))
insert into NewEmp([EmpId],[EmpName],[EmpAddress]) values (#Count,#EmpName,#EmpAddress)
end
Don't use a stored procedure. SQL Server has the option of computed columns which you can use to your advantage.
This will also take care of duplicate EmpId problem that may arise when a row is deleted from the table.
Just declare your table like this:
CREATE TABLE NewEmp
(
ID BIGINT Identity(1, 1) PRIMARY KEY,
[EmpId] AS 'A' + CONVERT(VARCHAR(10), 1000 + ID),
[EmpName] VARCHAR(255),
[EmpAddress] VARCHAR(255)
-- add more columns here if required...
)
Now you don't need to use any stored procedure etc. to generate your EmpId; it will be computed automatically.
You can use simple insert statement to add records to the table.
For example:
INSERT INTO NewEmp ([EmpName], [EmpAddress])
VALUES ('test name1', 'test address1')
INSERT INTO NewEmp ([EmpName], [EmpAddress])
VALUES ('test name2', 'test address2')
INSERT INTO NewEmp ([EmpName], [EmpAddress])
VALUES ('test name3', 'test address3')
INSERT INTO NewEmp ([EmpName], [EmpAddress])
VALUES ('test name4', 'test address4')
INSERT INTO NewEmp ([EmpName], [EmpAddress])
VALUES ('test name5', 'test address5')
INSERT INTO NewEmp ([EmpName], [EmpAddress])
VALUES ('test name6', 'test address6')
SELECT * FROM NewEmp
Output:
|----| ----- | ---------- |---------------|
| ID | EmpId | EmpName | EmpAddress |
|----| ----- | ---------- |---------------|
| 1 | A1001 | test name1 | test address1 |
| 2 | A1002 | test name2 | test address2 |
| 3 | A1003 | test name3 | test address3 |
| 4 | A1004 | test name4 | test address4 |
| 5 | A1005 | test name5 | test address5 |
| 6 | A1006 | test name6 | test address6 |
You are not passing EmpId for the procedure, ether give the id or change procedure so that EmpId dosen't need to be given
Create Table NewEmp
(
EmpId nvarchar(10),
EmpName Varchar(255),
EmpAddress Varchar(255),
MaxID INt
)
Declare #EmpId NVARCHAR(10),
#EmpName NVARCHAR(50),
#EmpAddress NVARCHAR(50),
#Count NVARCHAR(10),
#MaxID INT
SET #EmpId = NULL
SET #EmpName ='Alfaiz'
SET #EmpAddress ='Worli'
SELECT #MaxID=Max(MaxID) FROM NewEmp
IF #MaxID Is NUll
SET #MaxID=1
Else
Select #MaxID = Max(MaxID) + 1 FROM NewEmp
IF #MaxID is null
SET #Count='A'+Convert(VARCHAR(25),1001)
ELSE
SET #Count='A'+CONVERT(VARCHAR(25),1000 + #MaxID)
INSERT INTO NewEmp
([EmpId],[EmpName],[EmpAddress],MaxID)
VALUES
(#Count,#EmpName,#EmpAddress,#MaxID)
I need to analyze data from SQL server table. Table contains data connected with qualifications of all employyes in the company and has the following structure (simplified):
| User | Qualification | DateOfQualificationAssignment |
| user000 | Junior | 2014-01-15 |
| user000 | Middle | 2014-02-15 |
| user001 | Middle | 2014-02-02 |
| user001 | Senior | 2014-03-18 |
| user002 | Senior | 2014-02-19 |
| user003 | Junior | 2014-03-04 |
I need the way to determine number of employees having given qualification for the concrete date. It should be some sort of analyze("Qualification", "Date") function returning the folowing for these types of input data:
analyze("Junior", '2014-01-20') - returns 1 (it is user user000)
analyze("Junior", '2014-02-20') - returns 0 (because user000 became Middle on 2014-02-15)
analyze("Middle", '2014-02-25') - returns 2 (because user000 and user001 are having Middle qualification on 2014-02-25)
analyze("Middle", '2014-03-28') - returns 1 (user000 is still Middle, but user001 became Senior on 2014-03-18)
Currently I have no idea how to handle this efficiently. What approach can be used to achieve my goal?
Think this should satisfy your requirements:
create function dbo.analyze(#qualification varchar(50), #date date)
returns int
as
begin
declare #result int;
with cte
as
(
select t.*, rank() over (partition by t.[User] order by t.DateOfQualificationAssignment desc) r
from theTable t -- no clue what the real table is named
where t.DateOfQualificationAssignment < #date
)
select #result = count(*)
from cte
where cte.r = 1 and cte.Qualification = #qualification
return #result;
end
go
Tested with your data:
create table theTable
(
[User] varchar(50) not null,
Qualification varchar(50) not null,
DateOfQualificationAssignment date not null
)
go
insert into theTable([User],Qualification,DateOfQualificationAssignment)
values
('user000','Junior','20140115'),
('user000','Middle','20140215'),
('user001','Middle','20140202'),
('user001','Senior','20140318'),
('user002','Senior','20140219'),
('user003','Junior','20140304')
go
and the results:
select dbo.analyze('Junior','20140120') --returns 1
go
select dbo.analyze('Junior','20140220') --returns 0
go
select dbo.analyze('Middle','20140225') --returns 2
go
select dbo.analyze('Middle','20140328') --returns 1
go
Use row_number() over() in a derived table to enumerate the rows on DateOfQualificationAssignment descending partitioned by User where DateOfQualificationAssignment is less than the date you want to check on.
In the main query you count the rows with the enumerated value 1 and Qualification.
SQL Fiddle
MS SQL Server 2012 Schema Setup:
create table T
(
[User] char(7),
Qualification char(6),
DateOfQualificationAssignment date
)
insert into T values
('user000', 'Junior', '2014-01-15'),
('user000', 'Middle', '2014-02-15'),
('user001', 'Middle', '2014-02-02'),
('user001', 'Senior', '2014-03-18'),
('user002', 'Senior', '2014-02-19'),
('user003', 'Junior', '2014-03-04')
Query 1:
declare #Qualification char(6) = 'Middle'
declare #Date date = '2014-03-28'
select count(*)
from (
select T.Qualification,
row_number() over(partition by T.[User] order by T.DateOfQualificationAssignment desc) as rn
from T
where T.DateOfQualificationAssignment < #Date
) as T
where T.rn = 1 and
T.Qualification = #Qualification
Results:
| COLUMN_0 |
|----------|
| 1 |
I made this question a while back.
SQL Server making rows into columns
Basically, the person that answered explained very well what I needed to do. However, I encountered a problem
aID| status | group |
-----------------------
1 | acti | group1 |
2 | inac | group2 |
A3 | acti | group1 |
Second Table: This table is fixed. It has around 20 values and the IDs are all numbers
atID| traitname |
------------------
1 | trait1 |
2 | trait2 |
3 | trait3 |
Third Table: This table is used to identify the traits the assets in the first table have. The fields that have the same name as fields in the above tables are obviously linked.
tID| aID | atID | trait |
----------------------------------
1 | 1 | 1 | NAME |
2 | 1 | 2 | INFO |
3 | 2 | 3 | GOES |
4 | 2 | 1 | HERE |
Now, the user wants the program to output the data in the following format:
aID| status | group | trait1 | trait2 | trait 3
-------------------------------------------------
1 | acti | group1 | NAME | INFO | NULL
2 | inac | group2 | HERE | NULL | GOES
A3 | acti | group1 | NULL | NULL | NULL
Now, the problem here is that, as you can see, A3 has no trait. In the final view, I would want A3 to appear completely null in the traits. But it doesn't appear at all, even though it's there. Does anyone know how can I fix this?
Here is the query I am using:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(traitname)
from Table2
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT aid, status, [group],' + #cols + '
from
(
select t1.aid,
t1.status,
t1.[group],
t2.traitname,
t3.trait
from table1 t1
inner join table3 t3
on t1.aid = t3.aid
inner join table2 t2
on t3.atid = t2.atid
) x
pivot
(
max(trait)
for traitname in (' + #cols + ')
) p '
execute sp_executesql #query;
The problem is you are using an INNER JOIN on your tables. An INNER JOIN returns all rows that have matching data in both tables.
Since you want to return everything from Table1, you will alter your query to use a LEFT JOIN instead of the INNER JOIN:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(traitname)
from Table2
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT aid, status, [group],' + #cols + '
from
(
select t1.aid,
t1.status,
t1.[group],
t2.traitname,
t3.trait
from table1 t1
left join table3 t3
on t1.aid = t3.aid
left join table2 t2
on t3.atid = t2.atid
) x
pivot
(
max(trait)
for traitname in (' + #cols + ')
) p '
execute sp_executesql #query;
As a side note, it is difficult to tell what the data types on your join columns are. Your Table1.aid column appears to be a varchar because of the A3 value but your Table3.aid column looks to be an int. If your data types are not the same, then you will need to cast the data on the join similar to -- on t1.aid = cast(t3.aid as varchar(10))