I have a table 'A' with few columns say - ID, firstname,lastname,address and phonenumber.
I am populating this table on a daily basis using a query that joins few tables.
Now before loading the table, I need to check my query results against the table data and see if the data is already present.
If my table data and query results matches, then no need to insert the record.
if my table data and query result doesn't match then need to insert the record.
If the table data and the query result has updated record, then the data has to be inserted.
that is, If the Id,lastname,firstname, address are all same and only the PhoneNumber is changes in my query result. Then this record should also be inserted in the table A.
I tried a query to identify the Point -3, But I'm stuck how to proceed further and make thhose records to be inserted in table A.
SELECT DISTINCT *
FROM
(
SELECT * FROM
( SELECT [ID],FirstName, LastName,[PhoneNumber],[ExpDate] FROM [SCRATCH].[dbo].[A]
UNION ALL
SELECT D.[ID],FirstName, LastName,,[PhoneNumber],[ExpDate] FROM
S JOIN D ON D.ID = S.ID) Tbls
GROUP BY [ID],FirstName, LastName,[PhoneNumber],[ExpDate]
HAVING COUNT(*)<2) Diff
To get a list of rows that don't match between two tables - you can use EXCEPT. For example:
SELECT [ID],FirstName, LastName,[PhoneNumber],[ExpDate] FROM [SCRATCH].[dbo].[A]
Except
SELECT D.[ID],FirstName, LastName,,[PhoneNumber],[ExpDate] FROM S
From this - we can then construct an insert statement, here is an example with data:
Declare #tableS Table (ID int, FirstName varchar(30), LastName varchar(30), PhoneNumber varchar(12), ExpDate date);
Insert Into #tableS (ID, FirstName, LastName, PhoneNumber, ExpDate)
Values (1, 'Test', 'Testing', '111-111-1111', '2021-03-01');
Declare #tableA Table (ID int, FirstName varchar(30), LastName varchar(30), PhoneNumber varchar(12), ExpDate date)
Insert Into #tableA (ID, FirstName, LastName, PhoneNumber, ExpDate)
Values (2, 'Test', 'Testing', '222-222-2222', '2021-03-01')
, (3, 'Test', 'Testing', '333-333-3333', '2021-03-01');
--==== Insert new/changed rows into #tableS
Insert Into #tableS (ID, FirstName, LastName, PhoneNumber, ExpDate)
Select ID, FirstName, LastName, PhoneNumber, ExpDate From #tableA
Except
Select ID, FirstName, LastName, PhoneNumber, ExpDate From #tableS;
Select * From #tableS;
Insert Into #tableA (ID, FirstName, LastName, PhoneNumber, ExpDate)
Values (1, 'Test', 'Testing', '111-222-3333', '2021-03-02')
, (4, 'Test', 'Testing', '444-444-4444', '2021-03-04');
--==== Insert new/changed rows into #tableS
Insert Into #tableS (ID, FirstName, LastName, PhoneNumber, ExpDate)
Select ID, FirstName, LastName, PhoneNumber, ExpDate From #tableA
Except
Select ID, FirstName, LastName, PhoneNumber, ExpDate From #tableS;
Select * From #tableS;
You probably will need to adjust the columns used with EXCEPT so you are not comparing the ID and the ExpDate - but this should get you started.
Related
Please run the below code, these are all the same Customer because 2 of them have the same TaxNumber while another one matches one based on CompanyName. I need to link them all and set the ParentCompanyID based on who was created first. I am struggling to get them linked.
CREATE TABLE #Temp
(
CustomerID INT,
CustomerName VARCHAR(20),
CustomerTaxNumber INT,
CreatedDate DATE
)
INSERT INTO #Temp
VALUES (8, 'Company PTY',1234, '2019-09-20'),
(2, 'Company PT', 1234, '2019-09-24'),
(3, 'Company PTY',NULL, '2019-09-29')
SELECT * FROM #Temp
Below is the result that I require....
Any help will be appreciated.
Using case expression with first_value can give you the desired results:
SELECT CustomerID, CustomerName, CustomerTaxNumber, CreatedDate,
CASE WHEN CustomerTaxNumber IS NULL THEN
FIRST_VALUE(CustomerID) OVER(PARTITION BY CustomerName ORDER BY CreatedDate)
ELSE
FIRST_VALUE(CustomerID) OVER(PARTITION BY CustomerTaxNumber ORDER BY CreatedDate)
END As ParentCompanyID
FROM #Temp
Try this:
CREATE TABLE #Temp
(
CustomerID INT,
CustomerName VARCHAR(20),
CustomerTaxNumber INT,
CreatedDate DATE
)
INSERT INTO #Temp
VALUES (8, 'Company PTY',1234, '2019-09-20'),
(2, 'Company PT', 1234, '2019-09-24'),
(3, 'Company PTY',NULL, '2019-09-29')
SELECT DS.[CreatedDate] AS [FirstEntry]
,DS.[CustomerID] AS [ParentCompanyID]
,#Temp.*
FROM #Temp
CROSS APPLY
(
SELECT TOP 1 *
FROM #Temp
ORDER BY CreatedDate
) DS
DROP TABLE #Temp
You are condition is pretty simple - get the first record. If you need to group the records in some way, you can add additional filtering in the CROSS APPLY clause.
This question already has answers here:
get a comma delimited string from rows [duplicate]
(2 answers)
Closed 4 years ago.
I have a table like this.
Create table #temp
(
id int,
firstname varchar(50),
lastname varchar(50)
)
insert into #temp (id, firstname, lastname)
select 1,'mit','jain'
insert into #temp (id, firstname, lastname)
select 1,'mit','jain1'
insert into #temp (id, firstname, lastname)
select 1,'mit','jain2'
insert into #temp (id, firstname, lastname)
select 2,'mit','jain3'
insert into #temp (id, firstname, lastname)
select 2,'mit','jain4'
insert into #temp (id, firstname, lastname)
select 1,'mit','jain5'
insert into #temp (id, firstname, lastname)
select 1,'mit','jain6'
I want the table to be shown as below
id firstname lastname
----------------------------------------------
1 mit jain,jain1,jain2,jain5,jain6
2 mit jain2,jain4
I have tried the query as below
select
id, firstname,
substring((Select ', '+tc1.lastname AS [text()]
From #temp tc1
Inner Join #temp c1 On c1.id = tc1.id
Where tc1.firstname = c1.firstname
Order BY tc1.lastname
For Xml Path('')), 2, 1000) 'LastName1'
from #temp
group by id, firstname
But it's not working. Please help me out
You're part of the way there. The tradition method is using STUFF:
SELECT t.id, t.firstname,
STUFF((SELECT ', ' + sq.lastname
FROM #temp sq
WHERE sq.id = t.id
AND sq.firstname = t.firstname
ORDER BY sq.lastname
FOR XML PATH('')),1,1,'') AS lastname
FROM #temp t
GROUP BY t.id, t.firstname;
There are lots of answers on SO already on how to do this though, but you have shown effort. :)
For a time scheduling project, I have two tables: tbl_timeslots which holds available times with slotid as the primary key and totalmembers which counts the number of appointments made for this slot, and tbl_appointments with primary key apptid which holds the actual appointments, with slotid as a foreign key linking to the slot information.
I need to automatically update the totalmembers column any time an appointment is created/deleted/changed. The trigger I wrote (shown below) does not update the correct number of appointments in the tbl_timeslots column totalmembers.
CREATE TABLE tbl_timeslots
(
slotid int ,
fromdate datetime ,
todate datetime ,
totalmembers int
)
INSERT tbl_timeslots (slotid, fromdate, todate, totalmembers)
VALUES (1, '2016-01-01 10:00:00', '2016-01-01 11:00:00', 0)
INSERT tbl_timeslots (slotid, fromdate, todate, totalmembers)
VALUES (2, '2016-01-01 11:00:00', '2016-01-01 12:00:00', 0)
CREATE TABLE tbl_appointments
(
apptid int ,
slotid int ,
firstname varchar(10) ,
lastname varchar(10)
)
INSERT tbl_appointments (apptid, slotid, firstname, lastname)
VALUES (1, 1, 'Mark', 'Twain')
INSERT tbl_appointments (apptid, slotid, firstname, lastname)
VALUES (2, 1, 'Thomas', 'Jefferson')
INSERT tbl_appointments (apptid, slotid, firstname, lastname)
VALUES (3, 2, 'Donald', 'Duck')
CREATE TRIGGER [dbo].[tr_totalmembers]
ON [dbo].[TBL_appointments]
AFTER UPDATE, INSERT, DELETE
AS
BEGIN
UPDATE tbl_timeslots
SET totalmembers = (SELECT COUNT(1)
FROM tbl_appointments a
WHERE tbl_timeslots.slotid = a.slotid)
FROM inserted i
INNER JOIN deleted d ON i.apptid = d.apptid
WHERE
d.slotid <> i.slotid
AND (tbl_timeslots.slotid = i.slotid OR tbl_timeslots.slotid = d.slotid)
END
I just modified the trigger a bit and it worked for me :
CREATE TRIGGER [dbo].[tr_totalmembers]
ON [dbo].[TBL_appointments]
AFTER UPDATE, INSERT, DELETE
AS
BEGIN
UPDATE tbl_timeslots
SET totalmembers = a.cnt
from
(
SELECT slotid,COUNT(1) as cnt
FROM tbl_appointments
group by slotid
) a
WHERE
tbl_timeslots.slotid=a.slotid
END
Or in case if there is a specific problem please mention so that we could look into it .
A better way to compute totalmembers is to create and use an indexed view:
CREATE VIEW dbo.vw_timeslots_with_totalmembers
WITH SCHEMA_BINDING
AS
SELECT a.slotid, COUNT_BIG(*) AS totalmembers
FROM dbo.tbl_appointments a
GROUP BY a.slotid
GO
CREATE UNIQUE CLUSTERED INDEX IUC_vw_timeslots_with_totalmembers_slotid
ON dbo.vw_timeslots_with_totalmembers (slotid)
GO
DECLARE #slotid INT = 123
SELECT totalmembers
FROM dbo.vw_timeslots_with_totalmembers WITH(NOEXPAND) -- This table hint is needed in order to force usage of indexed view
WHERE slotid = #slotid
GO
Note: please read following notes regarding the proper configuration of SETtings (see section Required SET Options for Indexed Views): https://msdn.microsoft.com/en-us/library/ms191432.aspx .
Note #2: if last SELECT statement returns 0 rows this means that current slot doesn't have appointments (I assume that current slot is valid).
I wrote a multi statement table valued function. But I encountered slowness in this function.
CREATE FUNCTION [dbo].[userFunc]
(
-- Input param
)
RETURNS
#Results TABLE
(
UserId BIGInt,
FirstName BIGINT,
LastName INT
)
AS
BEGIN
INSERT INTO #Results
SELECT UserId, FirstName, LastName
FROM MyTable
RETURN
END
When I investigate this issue i found the cause of the slowness. Issue is with below Insert query.
INSERT INTO #Results
SELECT UserId, FirstName, LastName
FROM MyTable
But when I remove INSERT INTO #Results, the query is fast and return the result. Any idea why?
In the below sql code, what does T(C) mean? What is T and what is C?
declare #employeeData xml --this would be your XML input parameter
set #employeeData = '<employeeData>
<employee LastName="Smith" FirstName="Randolph" EmployeeID="1234567"/>
</employeeData>'
declare #xmlTable table (LastName nvarchar(255), FirstName nvarchar(255), EmployeeID int)
insert into #xmlTable (LastName, FirstName, EmployeeID)
select
C.value('#LastName','nvarchar(255)') as LastName,
C.value('#FirstName','nvarchar(255)') as FirstName,
C.value('#EmployeeID','int') as EmployeeID
from
#employeeData.nodes('/employeeData/employee') T(C)
select * from #xmlTable
Check MSDN: http://msdn.microsoft.com/en-us/library/ms188282.aspx
T - Table
C - Column