I have a table name SOURCETABLE with fields RollID, SMSID, FName, Lname.
The Destination table is DestTable with field ID, FirstName , LastName.
My task is to creat DestTable from the data of SOURCETABLE with following condition:
If RollID = NULL
ID = SMSID
else
ID = RollID
end if
Fname will go to Firstname and Lname will go to LastName
What statement I should write?
This should do it:
INSERT INTO DestTable (ID, FirstName, LastName)
SELECT COALESCE(RollId,SMSID), FName, LName
FROM SourceTable
You can read about what COALESCE does here:
http://msdn.microsoft.com/en-us/library/ms190349.aspx
INSERT INTO DestTable (Id, FirstName, LastName)
SELECT CASE WHEN ISNULL(RollId,'')='' THEN SMSId ELSE RollId END,
FName, LName FROM SOURCETABLE
Related
I have a SQL statement that concatenates First Name and Last Name of the person. I use the following SQL statement.
ISNULL(FullName.FirstName, '') + ' ' + ISNULL(FullName.LastName, '')
What I need is to change this to add the FirstName and LastName only if they are not both NULL. If one of them is not NULL, use that value.
Examples:
FirstName and LastName are NULL -> NULL
FirstName is John and LastName is NULL -> John
FirstName is NULL and LastName is Doe -> Doe
-> indicates the result
Use CONCAT() to concatenate without any NULL issues
TRIM() to remove any spaces for when one or both fields are missing
NULLIF() to replace '' with NULL if first and last name are both
missing
SQL Server 2017+ Solution
DROP TABLE IF EXISTS #emp
CREATE TABLE #emp (ID INT IDENTITY(1,1), FirstName VARCHAR(25), LastName VARCHAR(25));
INSERT INTO #emp
VALUES(null,null)
,('John',null)
,('Doe',null)
,('John', 'Doe');
SELECT FullName = NULLIF(TRIM(CONCAT(FirstName,' ',LastName)),'')
,*
FROM #emp
Actually if you just wrap you current expression inside TRIM() it should give you the behavior you want:
SELECT TRIM(ISNULL(FullName.FirstName, '') + ' ' +
ISNULL(FullName.LastName, '')) AS FullName
FROM yourTable;
In the event that only the first or last name be present, your original expression would leave a dangling leading/trailing space. The call to TRIM() fixes that by removing this extra space.
You can use simple case statement to solve this:
create table emp (emp_id int4, fname varchar(10), lname varchar(10));
insert into emp (emp_id) values(1);
insert into emp (emp_id,fname) values(2, 'John');
insert into emp (emp_id,lname) values(3, 'Doe');
insert into emp (emp_id,fname,lname) values(4, 'John', 'Doe');
select emp_id,fname, lname,
case
WHEN FNAME is not null and LNAME is not null then
FNAME||' '||LNAME
WHEN FNAME is not null and LNAME is NULL then
FNAME
WHEN FNAME is null and LNAME is not NULL then
LNAME
else null
end as FULL_NAME
from emp;
A better SQL Server 2017 solution:
Use the new CONCAT_WS function, which concatenates with a separator, ignoring nulls
CREATE TABLE #emp (ID INT IDENTITY(1,1), FirstName VARCHAR(25), LastName VARCHAR(25));
INSERT INTO #emp
VALUES(null,null)
,('John',null)
,('Doe',null)
,('John', 'Doe');
SELECT FullName = CONCAT_WS(' ', FirstName, LastName)
,*
FROM #emp;
db<>fiddle
I have table which stores details of each entity(employee, department). I want to build dynamic query from that table.
CREATE TABLE MyTable
(
Id int primary key,
EntityId int,
ColumnName varchar(100),
tablename varchar(100)
);
INSERT INTO MyTable (Id, EntityId, ColumnName, tableName)
VALUES (1,1,'name','employee');
INSERT INTO MyTable (Id, EntityId, ColumnName, tableName)
VALUES (2,1,'id','employee');
INSERT INTO MyTable (Id, EntityId, ColumnName, tableName)
VALUES (3,1,'salary','employee');
INSERT INTO MyTable (Id, EntityId, ColumnName, tableName)
VALUES (4,2,'name','departement');
INSERT INTO MyTable (Id, EntityId, ColumnName, tableName)
VALUES (5,2,'location','departement');
INSERT INTO MyTable (Id, EntityId, ColumnName, tableName)
VALUES (6,2,'id','departement');
Above is my table and insert scripts, How can I write a query which gives me output something like below.
SELECT id,name,salary from employee
SELECT id,location,name from departement
If i have multiple entity I should multiple select statements.
If despite the discouraging comments you still want to consider this approach, here is the query that constructs one query per entity:
SELECT entityid,
'SELECT ' ||
string_agg(columnname, ', ' ORDER BY id) ||
' FROM ' ||
tablename ||
';' AS query
FROM mytable
GROUP BY entityid, tablename;
Result with your example:
entityid | query
----------+---------------------------------------------
1 | SELECT name, id, salary FROM employee;
2 | SELECT name, location, id FROM departement;
(2 rows)
I have 2 tables which contains firstname, surname,dob.
First table has datatype as varchar for all columns and second table is varchar(50),varchar(50),datetime datatype.
Ex:
1st table
fname surname dob
a b 04/12/1948
a b 05/08/1984
2nd table
fname surname dob
a b 05/08/1984
a b 04/12/1948
when i do Intersect is not matching the decors (possibly b'ze of datatype)
and except give me result.
Is there any way to select all record from table 1 with matching records of table 2.
Any help much apprecciated
Both EXCEPT and INTERSECT work:
Declare #tblA AS TABLE(
FirstName VARCHAR(50),
SurName VARCHAR(50),
Dob VARCHAR(50)
)
Declare #tblB AS TABLE(
FirstName VARCHAR(50),
SurName VARCHAR(50),
Dob Date
)
INSERT INTO #tblA VALUES
('a','b','04/12/1948'),
('a','b','05/08/1948')
INSERT INTO #tblB VALUES
('a','b','04/12/1948'),
('a','b','05/09/1948')
SELECT
*
FROM #tblA
INTERSECT
SELECT
*
FROM #tblB
SELECT
*
FROM #tblA
EXCEPT
SELECT
*
FROM #tblB
Output:
SELECT fname, surname, CAST(dob AS DATETIME) AS dob FROM table1
INTERSECT
SELECT fname, surname, dob FROM table2
Use this query.
Select * from table1 as a
Inner join table2 as b
on a.fname = b.fname and a.surname = b.surname and cast(a.dob as date)=b.dob
SELECT * FROM #Table1 JOIN #Table2 ON #Table2.dob = CONVERT(DATETIME,#Table1.dob,101)
I'm inserting new records into a Person table, and if there's already a record with the same SSN, I want to backup this old record to another table (let's call it PersonsBackup) and update the row with my new values. There is an identity column in Person table that serves as my primary key, which has to be the same.
Source table structure:
Name | Addr | SSN
Person table structure:
PrimaryKeyID | Name | Addr | SSN
PersonBackup table structure:
BackupKeyID | Name | Addr | SSN | OriginalPrimaryKeyID
where OriginalPrimaryKeyID = PrimaryKeyID for the record that was backed up. How can this be done? I was thinking of using cursor to check if SSN matches, then insert that record accordingly, but I've been told that using cursors like this is very inefficient. Thanks for your help!
You can do so like this, combine the insert/update using MERGE
INSERT INTO PersonBackup
SELECT P.Name, P.Addr, P.SSN, P.PrimaryKeyID
FROM Person P
INNER JOIN source s ON P.SSD = s.SSD
MERGE Person AS target
USING (SELECT Name, Addr, SSN FROM SOURCE) AS source (NAME, Addr, SSN)
ON (target.SSN = source.SSN)
WHEN MATCHED THEN
UPDATE SET name = source.name, Addr = source.Addr
WHEN NOT MATCHED THEN
INSERT(Name, Addr, SSN)
VALUES(source.name, source.addr, source.SSN)
Here is some pseudocode to get you started:
Insert into PersonBackup table all Person data where SSN joins to Source data
Insert into Person table all Source data where SSN doesn't join to Person data
Update Person table all Source data where SSN joins to Person Data
So some hints:
Figure out a query that returns Person data where SSN is in the Source data.
Figure out a query that returns Source Data where SSN isn't in Person data.
Check out the syntax for INSERT INTO.
Check out the syntax for UPDATE FROM.
Assuming that BackupKeyID is identity in the PersonBackup table, you may try update statement with the output clause followed by insert of the records not existing in the target table:
update p
set p.Name = s.Name, p.Addr = s.Addr
output deleted.Name, deleted.Addr,
deleted.SSN, deleted.PrimaryKeyID into PersonBackup
from Source s
join Person p on p.SSN = s.SSN;
insert into Person (Name, Addr, SSN)
select s.Name, s.Addr, s.SSN
from Source s
where not exists (select 1 from Person where SSN = s.SSN);
or using insert into ... from (merge ... output) construct in a single statement:
insert into PersonBackup
select Name, Addr, SSN, PrimaryKeyID
from
(
merge Person p
using (select Name, Addr, SSN from Source) s
on p.SSN = s.SSN
when matched then
update set p.Name = s.Name, p.Addr = s.Addr
when not matched then
insert (Name, Addr, SSN) values (s.Name, s.Addr, s.SSN)
output $action, deleted.Name, deleted.Addr, deleted.SSN, deleted.PrimaryKeyID)
as U(Action, Name, Addr, SSN, PrimaryKeyID)
where U.Action = 'UPDATE';
DECLARE #TEMP TABLE (SSN VARCHAR(100),Name VARCHAR(MAX),Addr VARCHAR(MAX) ),
#SSN VARCHAR(100),
#Name VARCHAR(MAX),
#ADDR VARCHAR(MAX)
//INSERT YOUR VALUES INTO THIS TEMP VARIABLE FIRST.
SET #SSN = (SELECT SSN FROM #TEMP)
SET #Name = (SELECT NAME FROM #TEMP)
SET #Addr = (SELECT ADDR FROM #TEMP)
IF EXISTS (SELECT 1 FROM Person_table WHERE SSN = #SSN)
BEGIN
//BACKUP FIRST
INSERT INTO PersonBackup_table
SELECT * FROM Person_table WHERE SSN = #SSN
//UPDATE NEXT
UPDATE A
SET A.NAME = #NAME,
A.ADDR = #ADDR
FROM Person_table A
WHERE A.SSN = #SSN
END
ELSE
BEGIN
INSERT INTO Person_table VALUES #Name,#Addr,#SSN
END
I have to update the data of one of my SQL Server table that was mistakenly updated, and this caused data of one row's cell to over-write the next. Following is an example of what the table should have been in correct state:
FirstName LastName EmailID
--------------------------------------------------
abc xyz abc.xyz#something.com
def 321 def.321#something.com
ghi 123 ghi.123#something.com
Mistakenly the data has become:
FirstName LastName EmailID
---------------------------------------------
abc xyz something
def 321 abc.xyz#something.com
ghi 123 def.321#something.com
I know that the last one record will not be found but atleast other should be restored correctly
assuming your table is ordered by firstName, lastName you can use this:
declare #contact as table (firstName varchar(255), lastName varchar(255), emailID varchar(255))
insert into #contact (firstName, lastName, emailID)
values
('abc', 'xyz', 'something')
,('def', '321', 'abc.xyz#something.com')
,('ghi', '123', 'def.321#something.com');
with contactCTE(rowNo, firstName, lastName, emailID)
as
(
select
ROW_NUMBER() OVER (ORDER BY firstName, lastName DESC)
,firstName
,lastName
,emailID
from
#contact
)
update c1
set
emailID = c2.emailID
from
contactCTE c1
inner join contactCTE c2 on c1.rowNo +1 = c2.rowNo;
select * from #contact
If your data is ordered differently just modify the ORDER BY part in contactCTE to reflect this