max of date in a query in sql server - sql-server

I need help with writing part of query. Here's what I have
create table first_table(empid [varchar] (10) primary key not null,
DateInserted Datetime)
insert into first_table('1001','2012-02-13');
insert into first_table('1002','2013-02-13');
insert into first_table('1003','2014-02-11');
insert into first_table('1004','2012-02-13');
insert into first_table('2001','2012-02-12');
insert into first_table('2002','2014-02-13');
insert into first_table('5001','2014-02-13');
create table second_table(empid [varchar] (10) not null, CompanyID [varchar] (10) not null)
insert into second_table('1001','1');
insert into second_table('1002','1');
insert into second_table('1003','1');
insert into second_table('1004','1');
insert into second_table('2001','2');
insert into second_table('2002','2');
insert into second_table('5001','5');
create table valid_companies(CompanyID [varchar] (10) not null)
insert into valid_companies('1');
insert into valid_companies('2');
I want to select records from first_table that are valid_companies and with max date.
query should print
1003,1,2014-02-11
2002,2,2014-02-13
I am able to get
select DateInserted,ni.empID
,CompanyID
from
[dbo].[second_table] vw
inner join [dbo].[first_table] ni on ni.EmpID=vw.EmpID
where TagValue in(
SELECT DISTINCT [CompanyID]
FROM [dbo].[Valid_Companies]
)
. How to include max(DateInserted) in this query
Thx
R

try this
select e.empid, ec.CompanyID,
Max(e.DateInserted) LatestDate
from second_table ec
join first_table e
on e.empid = ec.empid
join valid_companies v
on v.CompanyID = ec.CompanyID
group by e.empid, ec.CompanyID

Related

How to delete and insert records using OUTPUT in T-SQL?

I am trying to delete some records and inserting into other table at the same time. While deleting it's a self join on that table which checks some conditions. I want to do both delete and inset operations using OUTPUT clause.
Code:
DELETE dbo.Test
OUTPUT DELETED.Recipient_Key,
DELETED.Home_Dt,
DELETED.Batch_No,
DELETED.Brand_Cd,
DELETED.Campaign_Cd,
DELETED.Campaign_Nm,
DELETED.CampaignType_Cd
INTO dbo.Error
FROM dbo.Test AS PR1
INNER JOIN Staging.dbo.Test AS PR2
ON PR2.Recipient_Key = PR1.Recipient_Key
AND PR2.Batch_No = PR1.Batch_No
AND PR2.Home_Dt <> PR1.Home_Dt;
With the self join you need to specify an alias.
drop table if exists #test;
create table #test (
Id int not null primary key clustered identity(1, 1)
, SomeColumn varchar(255) not null
);
drop table if exists #error;
create table #error (
Id int not null primary key clustered
, SomeColumn varchar(255) not null
);
insert into
#test (SomeColumn)
values
('A'), ('B'), ('C');
select * from #test;
select * from #error;
delete a
output
Deleted.Id, Deleted.SomeColumn
into
#error (Id, SomeColumn)
from
#test as a
inner join
#test as b
on
a.Id = b.Id
and a.Id % 2 = 1;
select * from #test;
select * from #error;

SQL Server 2008: Update/Insert data(multiple records) from multiple columns of different tables

I have to write a procedure to update table if record exists, else insert the data. I am getting records from different columns as comma-separated strings.
For example:
ID = "2,3,4,5";
Names = "S,D,G,H";
Approach that I have taken is: Created ID Table and Names Table with single column each. (Split function being used, returns table with single column which contains values). And then I am trying to insert/update the data. Insert is working fine. But for Update record, it's updating with incorrect values.
I am new to SQL and just can't get around with what am I doing wrong or if my approach is fine! Please help. Kindly note, in my approach I have used row_num to pick records in correct order from different temp tables. Following is my code:
Table Design:
CREATE TABLE [dbo].[TestMultipleInsert](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
[Number] [int] NOT NULL,
[Number1] [int] NULL,
CONSTRAINT [PK_TestMultipleInsert] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Code for Update/Insert
declare #names table (name varchar(50)); --Consider as split string values of Name Column
declare #numbers table (phone int); -- Consider as split string values of Number column
declare #number1s table (phone1 int); -- Consider as split string values of Number1 column
declare #MCodes table (Id int); --Consider as split string values of Id column. If Id = -1, then it's a new entry, else updated record.
-- Insert test data for running query
insert into #names (name) values('First');
insert into #names (name) values('Second');
insert into #names (name) values('Third');
insert into #names (name) values('Fourth');
insert into #numbers (phone) values(112);
insert into #numbers (phone) values(399);
insert into #numbers (phone) values(499);
insert into #numbers (phone) values(499);
insert into #number1s (phone1) values(112);
insert into #number1s (phone1) values(299);
insert into #number1s (phone1) values(399);
insert into #number1s (phone1) values(399);
insert into #MCodes (Id) values(54); --Update
insert into #MCodes (Id) values(-1); --Insert
insert into #MCodes (Id) values(50); --Update
insert into #MCodes (Id) values(-1); --Insert
--Query
insert into dbo.TestMultipleInsert (Name, Number, Number1)
select A.name, B.phone, C.phone1
from(
SELECT name,row_number() over (order by (select 0)) as row_num
FROM #names)A,
(SELECT phone,row_number() over (order by (select 0)) as row_num
FROM #numbers)B,
(SELECT phone1,row_number() over (order by (select 0)) as row_num
FROM #number1s)C,
(SELECT Id,row_number() over (order by (select 0)) as row_num
FROM #MCodes)D
where A.row_num=B.row_num and A.row_num = C.row_num and D.row_num = A.row_num and D.Id = -1
Update dbo.TestMultipleInsert
SET Name=A.Name, Number =B.phone, Number1= C.phone1
from(
SELECT name,row_number() over (order by (select 0)) as row_num
FROM #names)A,
(SELECT phone,row_number() over (order by (select 0)) as row_num
FROM #numbers)B,
(SELECT phone1,row_number() over (order by (select 0)) as row_num
FROM #number1s)C,
(SELECT Id,row_number() over (order by (select 0)) as row_num
FROM #MCodes)D
where D.row_num=B.row_num and D.row_num = C.row_num and D.row_num = A.row_num and D.Id <> -1 and D.Id = dbo.TestMultipleInsert.Id
select * from dbo.TestMultipleInsert;
Any help will be highly appreciated.
A1) I don't know what your big picture is, but your script is working as far as I can tell. The INSERT is inserting what I expect, and the UPDATE is updating the records that I expect. There's nothing technically wrong with using the row_number() over() function, but it's a little more straight-forward with the way I suggest below. (just preference in this situation)
Assuming you must have the four separate tables (temp tables), here is one way to do it. I added auto increment primary keys to the table variables to make joining the data more straight-forward.
You could also use a MERGE statement to do both the update and insert in one go. (About MERGE: https://msdn.microsoft.com/en-us/library/bb510625(v=sql.105).aspx)
--added auto increment primary key to avoid using window function row_nmber() over()...
declare #names table (pkey int primary key identity,name varchar(50)); --Consider as split string values of Name Column
declare #numbers table (pkey int primary key identity, phone int); -- Consider as split string values of Numer column
declare #number1s table (pkey int primary key identity, phone1 int); -- Consider as split string values of Number1 column
declare #MCodes table (pkey int primary key identity,Id int); --Consider as split string values of Id column. If Id = -1, then it's a new entry, else updated record.
-- Insert test data for running query
insert into #names (name) values('First');
insert into #names (name) values('Second');
insert into #names (name) values('Third');
insert into #names (name) values('Fourth');
insert into #numbers (phone) values(112);
insert into #numbers (phone) values(399);
insert into #numbers (phone) values(499);
insert into #numbers (phone) values(499);
insert into #number1s (phone1) values(112);
insert into #number1s (phone1) values(299);
insert into #number1s (phone1) values(399);
insert into #number1s (phone1) values(399);
insert into #MCodes (Id) values(54);
insert into #MCodes (Id) values(-1);
insert into #MCodes (Id) values(50);
insert into #MCodes (Id) values(-1);
--Insert Query
INSERT INTO dbo.TestMultipleInsert (Name, Number, Number1)
SELECT A.name, B.phone, C.phone1
FROM #names A
JOIN #numbers B ON B.pkey = A.pkey
JOIN #number1s C ON C.pkey = A.pkey
JOIN #MCodes D ON D.pkey = A.pkey
WHERE D.Id = -1
--Update query
UPDATE dbo.TestMultipleInsert
SET Name = upd.Name
, Number = upd.phone
, Number1 = upd.phone1
FROM(
SELECT A.name, B.phone, C.phone1, D.Id
FROM #names A
JOIN #numbers B on B.pkey = A.pkey
JOIN #number1s C on C.pkey = A.pkey
JOIN #MCodes D on D.pkey = A.pkey
WHERE D.Id <> -1
) upd
WHERE upd.Id = dbo.TestMultipleInsert.Id
A2) If you need to get a list of the identity values for an insert, declare a table variable (to get rows for all IDs) like this before your script that inserts:
DECLARE #myIDs table (ID int);
Then use the OUTPUT clause with your insert statement (if ID is your key column):
INSERT INTO tableBlah
OUTPUT INSERTED.ID INTO #myIDs
VALUES ...blah blah
You can then join your other queries (update, select etc) to the table variable to find the records that were just inserted.

Cascading data insert

I have these 3 tables:
CREATE TABLE tblPrimary(
Id INT IDENTITY(1,1) NOT NULL,
SampleID VARCHAR(8)
PRIMARY KEY (Id)
)
CREATE TABLE tblSecondary(
PrimaryId INT NOT NULL,
SampleName VARCHAR(50) NULL
)
CREATE TABLE tblSample(
SampleId VARCHAR(8) NOT NULL,
Name VARCHAR(50) NULL
PRIMARY KEY (SampleId)
)
Some sample data for tblSample
INSERT INTO tblSample VALUES ('A-1101', 'The CP 1014')
INSERT INTO tblSample VALUES ('A-1102', 'The NT 1014')
INSERT INTO tblSample VALUES ('A-1103', 'The LO 1014')
INSERT INTO tblSample VALUES ('A-1104', 'The AE 1014')
INSERT INTO tblSample VALUES ('A-1105', 'The PW 1014')
INSERT INTO tblSample VALUES ('A-1106', 'The QW 1014')
I'm currently inserting data from tblSample to tblPrimary with the following query:
INSERT INTO tblPrimary
SELECT s.SampleID FROM tblSample s
LEFT JOIN tblPrimary p on s.SampleId = p.SampleID
WHERE s.SampleId NOT IN (SELECT SampleID FROM tblPrimary)
Now I want to insert data into tblSecondary also, during the data insert into tblPrimary.
The newly generated `tblPrimary.PrimaryId` will be inserted into the tblSecondary.PrimiaryId` column
`tblSample.Name` will be inserted into the `tblSecondary.SampleName` column
It will be a cascading data inserting process
What do I need to do after the above insert query for this to get done?
I want the tblSecondary result to be as follows:
You will need a table variable and output clause for this something like....
DECLARE #NewIds (ID INT, SampleID varchar(8));
insert into tblPrimary(SampleID)
OUTPUT inserted.ID, inserted.SampleID INTO #NewIds (ID,SampleID )
select s.SampleID
from tblSample s
left join tblPrimary p on s.SampleId = p.SampleID
where s.SampleId not in (select SampleID from tblPrimary)
-- Now insert rows into tblSecondary table
INSERT INTO tblSecondary(PrimaryId, SampleName )
SELECT n.ID , S.Name
FROM tblSample s
INNER JOIN #NewIds n ON s.SampleId = n.SampleID

SQL Server Another simple question

I have 2 temp Tables [Description] and [Institution], I want to have these two in one table.
They are both tables that look like this:
Table1; #T1
|Description|
blabla
blahblah
blagblag
Table2; #T2
|Institution|
Inst1
Inst2
Inst3
I want to get it like this:
Table3; #T3
|Description| |Institution|
blabla Inst1
blahblah Inst2
blagblag Inst3
They are already in sort order.
I just need to get them next to each other..
Last time I asked was something almost the same.
I used this query
Create Table #T3
(
[From] Datetime
,[To] Datetime
)
INSERT INTO #T3
SELECT #T1.[From]
, MIN(#T2.[To])
FROM #T1
JOIN #T2 ON #T1.[From] < #T2.[To]
GROUP BY #T1.[From]
Select * from #T3
It did work for the date values, but it won't work here ? :s
Thank you.
One thing that concerns me is that you say that the values "are already in sort order". There really is no default sort order -- if you don't specify a sort order, you are at the mercy of SQL Server to determine the order in which the data is returned. The solution below assumes that there is some way to sort the data such that the records "match up" (using the ORDER BY clauses).
Hope this helps,
John
-- Table 1 test data
Create Table #T1
(
[Description] nvarchar(30)
)
INSERT INTO #T1 ([Description]) VALUES ('desc1')
INSERT INTO #T1 ([Description]) VALUES ('desc2')
INSERT INTO #T1 ([Description]) VALUES ('desc3')
-- Table 2 test data
Create Table #T2
(
[Institution] nvarchar(30)
)
INSERT INTO #T2 (Institution) VALUES ('Inst1')
INSERT INTO #T2 (Institution) VALUES ('Inst2')
INSERT INTO #T2 (Institution) VALUES ('Inst3')
-- Create table 3
Create Table #T3
(
[Description] nvarchar(30),
[Institution] nvarchar(30)
);
-- Use CTE2 to add row numbers to the data; use the row numbers to join the tables
-- you must specify the sort order for the data in the tables
WITH CTE1 (Description, RowNum) AS
(
SELECT [Description], ROW_NUMBER() OVER(ORDER BY [Description]) as RowNum
FROM #T1
),
CTE2 (Institution, RowNum) AS
(
SELECT Institution, ROW_NUMBER() OVER(ORDER BY Institution) as RowNum
FROM #T2
)
INSERT INTO #T3
SELECT CTE1.Description, CTE2.Institution
FROM CTE1
LEFT JOIN CTE2 ON CTE1.RowNum = CTE2.RowNum
Select * from #T3

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