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.
Related
I have to tables those are connected with foreign key relation
Address Table
id | address| country
1 | xyz | USA
2 | xyz | IND
Employee Table
id | name | company | Postal_address | Visiting_address
1 | Test | xyz | 1 | 2
How can I display Linked address to Employee using a SQL query like
Address | Country | Address Type
xyz | USA | Postal
xyz | IND | Visting
Is their any possible way to display linked address of any employee as list with Address type name using a SQL Server query or C#?
You can use SQL UNION and UNION ALL Keywords to achieve it, Live demo here
DECLARE #Address AS TABLE(id int, address varchar(50), country varchar(50))
INSERT INTO #Address
VALUES(1, 'xyz', 'USA'),
(2, 'xyz', 'IND')
DECLARE #Employee AS TABLE(id int, name varchar(50), company varchar(50), Postal_address int, Visiting_address int)
INSERT INTO #Employee
VALUES(1,'Test', 'xyz', 1, 2)
SELECT a.address, a.country, 'Postal' AS Address_Type
FROM #Employee e
INNER JOIN #Address a on a.id = Postal_address
WHERE e.id = 1
UNION ALL
SELECT a.address, a.country, 'Visting' AS Address_Type
FROM #Employee e
INNER JOIN #Address a on a.id = Visiting_address
WHERE e.id = 1
Output
address country Address_Type
xyz USA Postal
xyz IND Visting
I have tried with UNPIVOT. Read more on UNPIVOT.
The sample code is given below for reference.
CREATE TABLE #address (
id INT
,address VARCHAR(255)
,country VARCHAR(20)
);
CREATE TABLE #Employee (
id INT
,name VARCHAR(20)
,company VARCHAR(20)
,Postal_address INT
,visiting_address INT
);
INSERT INTO #address
VALUES (1 ,'xyz' ,'USA') ,( 2 ,'xyz' ,'India');
INSERT INTO #Employee
VALUES ( 1 ,'test' ,'xyz' ,1 ,2 );
WITH CTE_AddressUnpivot
AS (
SELECT name
,address_Type
,address_id
FROM (SELECT *
FROM #Employee
) AS src
UNPIVOT(address_id FOR address_Type IN ([postal_Address], [visiting_address])) AS addressUnpivot
)
SELECT addr.address
,addr.country
,CASE unp_addr.address_Type
WHEN 'Postal_address' THEN 'Postal'
WHEN 'visiting_address' THEN 'Visiting'
END AS Address_Type
FROM #address AS addr
JOIN CTE_AddressUnpivot AS unp_addr ON addr.id = unp_addr.address_id
You could also try with LEFT JOINs and COALESCE, like below:
declare #Address table (id int, address varchar(10), country varchar(10));
insert into #address values
(1,'xyz','USA'),
(2,'xyz','IND');
declare #Employee table (id int, name varchar(10),company varchar(10),Postal_address int,Visiting_address int);
insert into #employee values
(1, 'Test', 'xyz', 1, 2);
select a.address, a.country,
case when ePost.id is not null then 'Postal'
when eVisit.id is not null then 'Visiting'
else null end AddressType
from #address a
left join #employee ePost on a.address = ePost.company and a.id = ePost.Postal_address
left join #employee eVisit on a.address = eVisit.company and a.id = eVisit.Visiting_address
I have an table with ID NUMBER(18) and I have a class with properties public Int64 ID { get; set; } to mapping ID form C# vs Oracle.
My table definition
But I have an error when I get max ID like this:
Run query
SELECT MAX(ID) ID FROM MYTABLE
The system throw an error:
"Object of type 'System.Decimal' cannot be converted to type 'System.Int64'."
But when I run query like this:
SELECT ID FROM(
SELECT ID FROM MYTABLE ORDER BY ID DESC
) WHERE ROWNUM =1
It OK.
I don't know why (1) throw error, and why (2) done?
What is the difference between datatype (1) and (2)?
Possible scenario 1:
I guess that you have NULL values in table (so your both queries are not equivalent):
SELECT MAX(ID) ID FROM T_00_RQMM -- aggregate func ignore NULLS
But:
SELECT ID FROM(SELECT ID FROM T_00_RQMM ORDER BY ID DESC) WHERE ROWNUM = 1;
-- NULL is the max value
DBFiddle Demo
Anyway you should try mapping:
using System.Numerics;
...
public BigInteger ID { get; set; }
EDIT:
Possible scenario 2:
It may be problem with data type (then use explicit CAST):
SELECT CAST(MAX(ID) AS NUMBER(18,0)) ID FROM T_00_RQMM
DBFiddle Demo 2
Full demo:
CREATE TABLE T_00_RQMM (ID NUMBER(18,0));
INSERT INTO T_00_RQMM VALUES(NULL);
INSERT INTO T_00_RQMM VALUES(100);
CREATE TABLE t1 AS SELECT MAX(ID) ID FROM T_00_RQMM;
CREATE TABLE t2 AS SELECT ID FROM(SELECT ID FROM T_00_RQMM ORDER BY ID DESC)
WHERE ROWNUM = 1;
CREATE TABLE t3 AS SELECT CAST(MAX(ID) AS NUMBER(18,0)) ID FROM T_00_RQMM;
SELECT TABLE_NAME, COLUMN_NAME, DATA_PRECISION, DATA_SCALE
FROM all_tab_cols
where table_name in ('T1', 'T2', 'T3')
ORDER BY Table_name;
Output:
+------------+-------------+----------------+------------+
| TABLE_NAME | COLUMN_NAME | DATA_PRECISION | DATA_SCALE |
+------------+-------------+----------------+------------+
| T1 | ID | null | null |
| T2 | ID | 18 | 0 |
| T3 | ID | 18 | 0 |
+------------+-------------+----------------+------------+
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 |
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)
I am getting duplicated data within my GridView, while pulling info from a SQL Server. I am using stored procedures and using some C# to set the parameters then using the SqlDataSource to put the sql data from the stored procedure into a GridView. I have looked at some other problems just like mine, but the SQL scripting was different than mine. I also know that my C# code works just fine, but I will post that also,
Here is the code:
SQL:
SELECT
people.name, comage.age, grad.date
FROM
people
INNER JOIN
(SELECT age, MAX(term)[term]
FROM comage GROUP BY date) comage ON people.term = comage.term
INNER JOIN
(SELECT date, MAX(term)[term]
FROM grad GROUP BY date) grad ON people.term = grad.term
WHERE
people.ID = #ID
ORDER BY
LastName
ASP.net:
<asp:GridView ID="grid" runat="server"></GridView>
C# code:
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "prcedureName";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlParameter param = null;
param = cmd.Parameters.Add("#ID",System.Data.SqlDataType.NChar,255);
param.Direction = System.Data.ParameterDirection.Input;
param.value = in; //in is a string of some value
cmd.Connection = con; //con is a SqlConnection of some sort
SqlDataAdapter adp = new SqlDataAdapter(cmd);
SqlCommandBuilder command = new SqlCommandBuilder(adp);
DataTable data = new DataTable();
data.Locale = System.Globalization.CultureInfo.InvariantCulture;
adp.Fill(data);
grid.DataSource = data;
grid.AutoGenerateColumns = true;
grid.DataBind();
Here are the tables:
people table:
--------------------
|name | ID | term |
--------------------
|jeff | 0 | A |
|Jake | 1 | B |
--------------------
comage table:
--------------------
|Age | Term |
--------------------
|23 | A |
|25 | B |
--------------------
grad table:
--------------------
| Date | Term |
--------------------
| DEC | A |
| SUM | B |
--------------------
Are you sure that you don't have your aggregates backwards in your SQL? I would have expected it to be written more like this:
SELECT people.name, Max(comage.age) age, Max(grad.date) date
FROM people
INNER JOIN comage ON people.term = comage.term
INNER JOIN grad ON people.term = grad.term
WHERE people.ID = #ID
GROUP BY people.name
ORDER BY LastName
Which would produce a result set like this:
name | age | date
------------------
Jeff | 23 | DEC
Jake | 25 | SUM
I only get one record, based on the ID I submitted.
DECLARE #People TABLE ([Name] VARCHAR(10), ID INT, Term VARCHAR(10));
DECLARE #Comage TABLE (Age INT, Term VARCHAR(10));
DECLARE #Grad TABLE ([Date] VARCHAR(10), Term VARCHAR(10));
DECLARE #ID INT;
SET #ID = 0;
INSERT INTO #People VALUES ('Jeff', 0, 'A');
INSERT INTO #People VALUES ('Jake', 1, 'B');
INSERT INTO #Comage VALUES (23, 'A');
INSERT INTO #Comage VALUES (25, 'B');
INSERT INTO #Grad VALUES ('DEC', 'A');
INSERT INTO #Grad VALUES ('SUM', 'B');
SELECT age, MAX(term) [term]
INTO #Comage
FROM #Comage
GROUP BY [Age]
SELECT [Date], MAX(term) [term]
INTO #Grad
FROM #Grad GROUP BY [Date]
SELECT
p.name, c.age, g.[Date]
FROM
#People p
INNER JOIN #Comage c
ON c.term = p.term
INNER JOIN #Grad g
ON g.term = p.term
WHERE
p.ID = #ID
DROP TABLE #Comage
DROP TABLE #Grad