Copy Data between SQL Databases - sql

I have 2 Databases (Database1) and (Database2)
DataBase1 has one table (table1)
DataBase2 has one table (table2)
DataBase1.table1 (id as int, code as nvarchar(20), PunhTime as datetime)
DataBase2.table2 (code2 as nvarchar(20), MyDate as datetime, Time1 as nvarchar(8) , Time2 as nvarchar(8))
could Achieve that through SQL ?
thanks in advance
here photo to show how data should copy ..
enter image description here

You may try this
WITH cte_PunchTime AS (
SELECT Code, CONVERT(date, PunchTime) as MyDate, CONVERT(time, PunchTime) as [Time], ROW_NUMBER() OVER (PARTITION BY Code ORDER BY PunchTime) AS [Rank]
FROM DataBase1.table1
)
INSERT INTO DataBase2.table2( Code2, MyDate, Time1, Time2)
SELECT Code, MyDate, MIN([Time]) AS Time1, MAX([Time]) AS Time2
FROM cte_PunchTime
GROUP BY Code, MyDate
You can use the Rank and PIVOT to use it for more than two columns. But number of columns need to be defined. For example, below code is for 4 columns.
WITH cte_Product AS (
SELECT Code, CONVERT(date, PunchTime) as MyDate, CONVERT(time, PunchTime) as [Time]
, ROW_NUMBER() OVER (PARTITION BY Code ORDER BY PunchTime) AS [Rank]
FROM DataBase1.table1
)
INSERT INTO DataBase2.table2( Code, MyDate, Time1, Time2, Time3, Time4)
SELECT * FROM cte_Product
PIVOT (
Min([Time]) FOR [Rank] IN ([1], [2], [3], [4])
) Result;

If they are running the databases on the same server, it is relatively easy to do:
INSERT INTO dbo.DataBase2.table2
(
[code2],
[Time1]
)
SELECT [code], [PunhTime]
FROM dbo.DataBase1.table1
You only have to change the column, since I it is unclear which column should go to which column.

Related

PIVOT without aggregate function ID as column names

I have a query
SELECT a.Name, b.Date FROM
Table1 a
JOIN Table2 b on a.deviceID=b.id
where a.date > '2022-10-01'
Which gives me result
Name Date
A1 '2022-10-01 12:13'
A2 '2022-10-02 14:15'
A2 '2022-10-02 15:16'
A5 '2022-10-03 16:19'
etc.
The result I want to achieve is
A1 A2 A5
'2022-10-01 12:13' '2022-10-02 14:15''2022-10-03 16:19'
'2022-10-02 15:16'
The perfect result would be to receive only one date of each day. Can I do it with pivot?
Pivoting cannot be done (in T-SQL) without aggregation. As for what you want to achieve, seems you need to PIVOT/conditionally aggregate on the value of Name and group on the value of a ROW_NUMBER.
I, personally, prefer using conditional aggregation over the restrictive PIVOT operator, but I have included examples of both:
USE Sandbox;
GO
CREATE TABLE #YourData (Name char(2),
Date datetime2(0));
GO
INSERT INTO #YourData (Name,
Date)
VALUES('A1','2022-10-01T12:13:00'),
('A2','2022-10-02T14:15:00'),
('A2','2022-10-02T15:16:00'),
('A5','2022-10-03T16:19:00');
GO
WITH RNs AS(
SELECT [Name],
[Date],
ROW_NUMBER() OVER (PARTITION BY [Name] ORDER BY [Date]) AS RN
FROM #YourData)
SELECT MAX(CASE [Name] WHEN 'A1' THEN [Date] END) AS A1,
MAX(CASE [Name] WHEN 'A2' THEN [Date] END) AS A2,
MAX(CASE [Name] WHEN 'A5' THEN [Date] END) AS A5
FROM RNs
GROUP BY RN;
GO
SELECT P.A1,
P.A2,
P.A5
FROM (SELECT [Name],
[Date],
ROW_NUMBER() OVER (PARTITION BY [Name] ORDER BY [Date]) AS RN
FROM #YourData)YD
PIVOT(MAX([date])
FOR [Name] IN (A1,A2,A5))P;
GO
DROP TABLE #YourData;
If you want to pivot but keep all your related values in the same field rather than creating fake rows, you can use STRING_AGG. You can replace the "," separator with a CHAR(10), or perhaps an HTML to add a line break. You won't see it in SSMS but depending on your front end, that would render the two items, one under each other.
DROP TABLE IF EXISTS #YourData
CREATE TABLE #YourData (Name char(2),
Date datetime2(0));
GO
INSERT INTO #YourData (Name,
Date)
VALUES('A1','2022-10-01T12:13:00'),
('A2','2022-10-02T14:15:00'),
('A2','2022-10-02T15:16:00'),
('A5','2022-10-03T16:19:00');
GO
DECLARE #Seperator VARCHAR(10) = ' , '
SELECT
[A1] , [A2], [A3], [A4], [A5]
FROM
(
SELECT name, STRING_AGG(date,#Seperator) AS Dates
FROM #YourData
GROUP BY Name
) AS SourceTable
PIVOT
(
MAX(Dates)
FOR Name IN ([A1], [A2], [A3], [A4], [A5])
) AS PivotTable;

INSERT INTO #tmp from CTE query

I want to be able to insert the results of this CTE query into a temp table so I can sum the Total column.
CREATE TABLE #tmp
(
SerialNumber NVARCHAR(50),
StartDateTime NVARCHAR(50),
EndDateTime NVARCHAR(50),
Total NVARCHAR(50)
)
;WITH cte1 AS
(
SELECT
*,
CASE
WHEN Temperature > #maxthreshold AND LAG(Temperature) OVER (PARTITION BY SerialNumber ORDER BY CombineDateTime) IS NULL THEN 1
WHEN Temperature <= #maxthreshold AND LEAD(Temperature) OVER (PARTITION BY SerialNumber ORDER BY CombineDateTime) > #maxthreshold THEN 1
WHEN Temperature <= #maxthreshold AND LAG(Temperature) OVER (PARTITION BY SerialNumber ORDER BY CombineDateTime) > #maxthreshold THEN 1
END AS chg
FROM
[RawData]
WHERE
SerialNumber = #_Serial
AND CombineDateTime BETWEEN #_DateFrom AND #_DateTo
), cte2 AS
(
SELECT
*,
SUM(chg) OVER (PARTITION BY SerialNumber ORDER BY CombineDateTime) AS grp
FROM
cte1
)
INSERT INTO #tmp
SELECT
SerialNumber,
MIN(CombineDateTime) AS StartDateTime,
MAX(CombineDateTime) AS EndDateTime,
DATEDIFF(SECOND, MIN(CombineDateTime), MAX(CombineDateTime)) / 60.0 AS 'Total'
FROM
cte2
GROUP BY
SerialNumber, grp
HAVING
MAX(Temperature) > #maxthreshold)
SELECT *
FROM #tmp
DROP TABLE #tmp
I have tried putting the insert in various places, but it does not insert, I have tried the following answers. I am confused as to why the insert won't work as it is outside of the recursion.
Answer 1
Answer 2
TIA

SQL - condition on a timestampdiff

I would like to get the average time of solution time for tickets
from state 'billet ouvert' to state 'résolu'.
Table Sample
The queries I tried:
Query 1:
SELECT
title AS 'Etat', ticket_id, user_id,
AVG(TIMESTAMPDIFF(HOUR,
helpdesk_followup.date having title in ('billet ouvert'),
helpdesk_followup.date having title in ('résolu'))
) AS 'moyenne'
FROM helpdesk_followup
GROUP BY user_id;
Query 2:
SELECT
title AS 'Etat', ticket_id, user_id,
AVG(TIMESTAMPDIFF(HOUR,
helpdesk_followup.date as date1,
helpdesk_followup.date as date2)
) AS 'moyenne'
FROM helpdesk_followup
WHERE date1 having title IN 'résolu'
AND date2 having title IN 'billet ouvert'
GROUP BY user_id;
But these queries doesn't get the result I need. How can I add condition to a timestampdiff?
The first column is the starting event and the second column is the end event.
I have done the average in minutes. This SQL works off the title which you may wish to tweak to something more distinct
select a.title, b.title, avg(DateDiff(MINUTE, '00:00:00', b.[date] ) - DateDiff(MINUTE, '00:00:00', a.[date] ) ) from
(select *, row_number() over (order by [date]) hf from helpdesk_followup) a
join (select *, row_number() over (order by [date]) hf from helpdesk_followup) b on (a.hf=b.hf-1)
group by
a.title, b.title
I have left out the user_id from the query as I'm unsure if you wish to break it down using that field.
Hopefully its a start for you to amend into what you need
EDIT: Here is the test data I used for the query
CREATE TABLE [dbo].[helpdesk_followup](
[title] [varchar](50) NULL,
[ticket_id] [int] NULL,
[user_id] [int] NULL,
[date] [datetime] NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
INSERT [dbo].[helpdesk_followup] ([title], [ticket_id], [user_id], [date]) VALUES (N'billet ouvert', 133, NULL, CAST(N'2015-07-22 15:36:00.000' AS DateTime))
GO
INSERT [dbo].[helpdesk_followup] ([title], [ticket_id], [user_id], [date]) VALUES (N'résolu', 133, 19, CAST(N'2015-07-23 15:36:00.000' AS DateTime))
GO
INSERT [dbo].[helpdesk_followup] ([title], [ticket_id], [user_id], [date]) VALUES (N'billet ouvert', 134, 15, CAST(N'2015-07-23 15:36:00.000' AS DateTime))
GO
INSERT [dbo].[helpdesk_followup] ([title], [ticket_id], [user_id], [date]) VALUES (N'résolu', 134, 21, CAST(N'2015-07-27 15:36:00.000' AS DateTime))
GO

How to use the minimum date from three available - SQL

I'm trying to plug a formula into a query to pull back how much should have run on a particular contract.
The formula itself is quite simple, but I can't find anywhere how to take the minimum date between 3, based on each record separately.
I need to calculate which is the earliest of Term_date, Suspend_date and today's date, some of which may be NULL, on each contract.
And interesting way to approach this is to use cross apply:
select t.contractid, mindte
from table t cross apply
(select min(dte) as mindte
from (values(t.term_date), (t.suspend_date), (getdate())) d(dte)
) d;
CASE
WHEN Term_date < Suspend_date AND Term_date < GETDATE() THEN Term_date
WHEN Suspend_date < GETDATE() THEN Suspend_date
ELSE GETDATE()
END AS MinimumDate
I know a CASE statement will be suggested, but I thought I'd try something different:
;WITH cte (RecordID, CheckDate) AS
( SELECT RecordID, Term_date FROM sourcetable UNION ALL
SELECT RecordID, Suspend_date FROM sourcetable UNION ALL
SELECT RecordID, GETDATE() FROM sourcetable )
SELECT src.RecordID, src.Field1, src.Field2, MinDate = MIN(cte.CheckDate)
FROM sourcetable src
LEFT JOIN cte ON cte.RecordID = src.RecordID
GROUP BY src.RecordID, src.Field1, src.Field2
Here is a method using cross apply to generate a work table from which you can get the minimum date:
-- mock table with sample testing data
declare #MyTable table
(
id int identity(1,1) primary key clustered,
term_date datetime null,
suspend_date datetime null
)
insert into #MyTable (term_date, suspend_date)
select null, null
union all select '1/1/2015', null
union all select null, '1/2/2015'
union all select '1/3/2015', '1/3/2015'
union all select '1/4/2015', '1/5/2015'
union all select '1/6/2015', '1/5/2015'
select * from #MyTable
select datevalues.id, min([date])
from #MyTable
cross apply
(
values (id, term_date), (id, suspend_date), (id, getdate())
) datevalues(id, [date])
group by datevalues.id

SQL: Remove duplicates

How do I remove duplicates from a table that is set up in the following way?
unique_ID | worker_ID | date | type_ID
A worker can have multiple type_ID's associated with them and I want to remove any duplicate types. If there is a duplicate, I want to remove the type with the most recent entry.
A textbook candidate for the window function row_number():
;WITH x AS (
SELECT unique_ID
,row_number() OVER (PARTITION BY worker_ID,type_ID ORDER BY date) AS rn
FROM tbl
)
DELETE FROM tbl
FROM x
WHERE tbl.unique_ID = x.unique_ID
AND x.rn > 1
This also takes care of the situation where a set of dupes on (worker_ID,type_ID) shares the same date.
See the simplified demo on data.SE.
Update with simpler version
Turns out, this can be simplified: In SQL Server you can delete from the CTE directly:
;WITH x AS (
SELECT unique_ID
,row_number() OVER (PARTITION BY worker_ID,type_ID ORDER BY date) AS rn
FROM tbl
)
DELETE x
WHERE rn > 1
delete from table t
where exists ( select 1 from table t2
where t2.worker_id = t.worker_id
and t2.type_id = t.type_id
and t2.date < t.date )
HTH
DELETE FROM #t WHERE unique_Id IN
(
SELECT unique_Id FROM
(
SELECT unique_Id
,Type_Id
,ROW_NUMBER() OVER (PARTITION BY worker_Id, type_Id ORDER BY date) AS rn
FROM #t
) Q
WHERE rn > 1
)
And to test...
DECLARE #t TABLE
(
unique_ID INT IDENTITY,
worker_ID INT,
date DATETIME,
type_ID INT
)
INSERT INTO #t VALUES (1, DATEADD(DAY, 1, GETDATE()), 1)
INSERT INTO #t VALUES (1, GETDATE(), 1)
INSERT INTO #t VALUES (2, GETDATE(), 1)
INSERT INTO #t VALUES (1, DATEADD(DAY, 2, GETDATE()), 1)
INSERT INTO #t VALUES (1, DATEADD(DAY, 3, GETDATE()), 2)
SELECT * FROM #t
DELETE FROM #t WHERE unique_Id IN
(
SELECT unique_Id FROM
(
SELECT unique_Id
,Type_Id
,ROW_NUMBER() OVER (PARTITION BY worker_Id, type_Id ORDER BY date) AS rn
FROM #t
) Q
WHERE rn > 1
)
SELECT * FROM #t
you may use this query
delete from worker where unique_id in (
select max(unique_id) from worker group by worker_ID , type_ID having count(type_id)>1)
here i am assuming worker as your table name