I created a query to delete some record in MariaDB
Query :
DELETE
FROM
HrAttLogsFormatted
WHERE
DateIn = '2019-04-10'
AND Late != ''
AND ( FingerId, CreatedDate ) IN (
SELECT
FingerId,
MAX( CreatedDate )
FROM
HrAttLogsFormatted
WHERE
DateIn = '2019-04-10'
AND Late != ''
AND FingerId IN ( SELECT FingerId FROM HrAttLogsFormatted WHERE DateIn = '2019-04-10' AND Late != '' GROUP BY FingerId HAVING COUNT( FingerId ) > 1 )
GROUP BY
FingerId
)
Result :
Table 'HrAttLogsFormatted' is specified twice, both as a target for
'DELETE' and as a separate surce for data
But with the query I made unsuccessfully, is there a way to solve it?
Thank you in advance
[EDIT-SOLVED] It's Solved with simply apply and query
DELETE t1
FROM HrAttLogsFormatted t1
INNER JOIN
(
SELECT FingerId, MinCreatedDate
FROM
(
SELECT FingerId, MIN(CreatedDate) AS MinCreatedDate
FROM HrAttLogsFormatted
WHERE DateIn = '2019-05-03' AND Late != ''
GROUP BY FingerId HAVING COUNT(FingerId) > 1
) x
) t2
ON t1.FingerId = t2.FingerId AND t1.CreatedDate = t2.MinCreatedDate;
I would try writing this as a delete join:
DELETE t1
FROM HrAttLogsFormatted t1
INNER JOIN
(
SELECT FingerId, MIN(CreatedDate) AS MinCreatedDate
FROM HrAttLogsFormatted
WHERE DateIn = '2019-04-10' AND Late != ''
GROUP BY FingerId
HAVING COUNT(FingerId) > 1
) t2
ON t1.FingerId = t2.FingerId AND t1.CreatedDate = t2.MinCreatedDate;
If you really wanted to stick with your current query, you might be able to make it work by adding an additional subquery around the WHERE IN clause:
AND (FingerId, CreatedDate) IN (
SELECT FingerId, MinCreatedDate
FROM
(
SELECT FingerId, MIN(CreatedDate) AS MinCreatedDate
FROM HrAttLogsFormatted
...
) x )
But, I would use the version I gave, because it is simpler.
Related
I'm having trouble with writing a query to get difference between the UpdateDate and the CreationDate of 2 records if the ID is the lowets and the difference between the most recent and second most recent UpdateDate.
Here's my Query:
SELECT
a.ID, a.RequestID, b.KrStatus, b.CrDate , b.UpdateDate,
DATEDIFF (HOUR, b.CrDate, b.UpdateDate) AS TimeDifference,
CASE WHEN a.ID = (SELECT MAX(a.ID) FROM [dbo].[Krdocs_hist] a WHERE a.RequestID = 1)
THEN 'YES'
ELSE 'NO'
END AS isMax,
CASE WHEN a.ID = (SELECT MIN(a.ID) FROM [dbo].[Krdocs_hist] a WHERE a.RequestID = 1)
THEN 'YES'
ELSE 'NO'
END AS isMi
FROM [dbo].[Krdocs_hist] a, [dbo].Krdocs_Details_hist b
WHERE
a.RequestId = b.RequestId
and a.ID = b.ID
and a.RequestId = 1
ORDER BY b.RequestID
Here's my current result:
What I'd like to do is get the last possible record, check to see if there was an existing one before it. If there wasn't compare the UpdateDate and CrDate (UpdateDate minus CrDate. If there was a record before this I want to do the UpdateDate minus the previous UpdateDate.
Using this query:
SELECT b.Id, b.RequestId, b.UpdateDate, b.KrStatus
FROM [dbo].[Krdocs_Details_hist] b
WHERE b.RequestId = 1
Has this result:
And using this query:
SELECT a.*
FROM [dbo].[Krdocs_hist] a
WHERE RequestId = 1
Has this result:
UPDATE
Since LAG is available from SQL 2012, you can use like below:
SELECT
ID,
RequestID,
CrDate,
UpdateDate,
KrStatus,
DATEDIFF(HOUR, PreviousUpdateDate, UpdateDate) as TimeDifference
FROM
(SELECT
ID,
RequestID,
CrDate,
UpdateDate,
KrStatus,
LAG(UpdateDate, 1, CrDate) OVER (ORDER BY YEAR(ID)) AS PreviousUpdateDate
FROM [dbo].Krdocs_Details_hist) as tmp
I think you can try like this:
SELECT
CASE
WHEN COUNT(*) <= 1 THEN DATEDIFF(HOUR,
(SELECT CrDate FROM [dbo].Krdocs_Details_hist),
(SELECT UpdateDate FROM [dbo].Krdocs_Details_hist))
WHEN COUNT(*) > 1 THEN DATEDIFF(HOUR,
(SELECT MAX(UpdateDate) FROM [dbo].Krdocs_Details_hist WHERE UpdateDate < ( SELECT MAX(UpdateDate) FROM [dbo].Krdocs_Details_hist)),
(SELECT MAX(UpdateDate) FROM [dbo].Krdocs_Details_hist))
END AS TimeDifference
FROM [dbo].Krdocs_Details_hist
Here is the picture what is the problem exactly.
I want to sum overed_qty into one row by order and article, and that's my confusion.
-- Insert statements for procedure here
SELECT table_PrintJob.order_name, table_PrintJob.article_name, table_Orders.qty AS order_qty,
(CASE WHEN COUNT(*) OVER (PARTITION BY table_PrintJob.order_name,table_PrintJob.article_name) > 1
THEN SUM(table_PrintJob.qty * table_PrintJob.qty_operation) - MIN(SUM(table_PrintJob.qty * table_PrintJob.qty_operation))
OVER (PARTITION BY table_PrintJob.order_name, table_PrintJob.article_name)
ELSE SUM(table_PrintJob.qty * table_PrintJob.qty_operation) END) AS overed_pieces,
SUM(table_PrintJob.repaired) AS repaired_qty
FROM table_PrintJob
INNER JOIN table_Orders On table_PrintJob.order_name = table_Orders.name
WHERE table_PrintJob.date_time BETWEEN #start_time AND #end_time
GROUP BY table_PrintJob.order_name,
table_PrintJob.article_name,
table_Orders.qty,
table_PrintJob.operation
ORDER BY table_PrintJob.order_name
So i'm found the solution:
SELECT * INTO #tmpTable
FROM (
-- Insert statements for procedure here
SELECT table_PrintJob.order_name, table_PrintJob.article_name, table_Orders.qty AS order_qty,
(CASE WHEN COUNT(*) OVER (PARTITION BY table_PrintJob.order_name,table_PrintJob.article_name) > 1
THEN SUM(table_PrintJob.qty * table_PrintJob.qty_operation) - MIN(SUM(table_PrintJob.qty * table_PrintJob.qty_operation))
OVER (PARTITION BY table_PrintJob.order_name, table_PrintJob.article_name)
ELSE SUM(table_PrintJob.qty * table_PrintJob.qty_operation) END) AS overed_pieces,
SUM(table_PrintJob.repaired) AS repaired_qty
--INTO v_tx
FROM table_PrintJob
INNER JOIN table_Orders On table_PrintJob.order_name = table_Orders.name
WHERE table_PrintJob.date_time BETWEEN #start_time AND #end_time
GROUP BY table_PrintJob.order_name,
table_PrintJob.article_name,
table_Orders.qty,
table_PrintJob.operation
--ORDER BY table_PrintJob.order_name
) AS x
select order_name,
article_name,
order_qty,
sum(#tmpTable.overed_pieces),
sum(#tmpTable.repaired_qty)
from #tmpTable
--INNER JOIN table_Orders On v_tx.order_name = table_Orders.name
group by order_name,
article_name,
#tmpTable.order_qty
I have data in my table like this
RepID|Role|Status|StartDate |EndDate |
-----|----|------|----------|----------|
10001|R1 |Active|01/01/2015|01/31/2015|
-----|----|------|----------|----------|
10001|R1 |Leavee|02/01/2015|02/12/2015|
-----|----|------|----------|----------|
10001|R1 |Active|02/13/2015|02/28/2015|
-----|----|------|----------|----------|
10001|R2 |Active|03/01/2015|03/18/2015|
-----|----|------|----------|----------|
10001|R2 |Leave |03/19/2015|04/10/2015|
-----|----|------|----------|----------|
10001|R2 |Active|04/11/2015|05/10/2015|
-----|----|------|----------|----------|
10001|R1 |Active|05/11/2015|06/13/2015|
-----|----|------|----------|----------|
10001|R1 |Leave |06/14/2015|12/31/9998|
-----|----|------|----------|----------|
I am looking for the output like this,
RepID|Role|StartDate |EndDate |
-----|----|----------|----------|
10001|R1 |01/01/2015|02/28/2015|
-----|----|----------|----------|
10001|R2 |03/01/2015|05/10/2015|
-----|----|----------|----------|
10001|R1 |05/11/2015|12/31/9998|
-----|----|----------|----------|
Whenever only the role change happens, I need to capture the start and EndDate. I tried different ways but couldn't get the output.
Any help is appreciated.
Below is the SQL i tried with but it doesnt help,
SELECT T1.RepID, T1.Role, Min(T1.StartDate) AS StartDate, Max(T1.EndDate) AS EndDate
FROM
(SELECT rD1.RepID, rD1.Role, rD1.StartDate, rD1.EndDate
FROM repDetails rD1
INNER JOIN repDetails rD2
ON rD2.RepID = rD1.RepID AND rD2.StartDate = DateAdd (Day, 1, rD1.EndDate) AND (rD2.Role = rD1.Role OR (rD2.Role IS NULL AND rD1.Role IS NULL) OR (rD2.Role = '' AND rD1.Role = ''))
UNION
SELECT rD2.RepID, rD2.Role, rD2.StartDate, rD2.EndDate
FROM repDetails rD1
INNER JOIN repDetails rD2
ON rD2.RepID = rD1.RepID AND rD2.StartDate = DateAdd (Day, 1, rD1.EndDate) AND (rD2.Role = rD1.Role OR (rD2.Role IS NULL AND rD1.Role IS NULL) OR (rD2.Role = '' AND rD1.Role = ''))
) T1
GROUP BY T1.RepID, T1.Role
UNION
SELECT EP.RepID, EP.Role AS DataValue, EP.StartDate, EP.EndDate
FROM repDetails EP
LEFT OUTER JOIN
(SELECT rD1.RepID, rD1.Role, rD1.StartDate, rD1.EndDate
FROM repDetails rD1
INNER JOIN repDetails rD2
ON rD2.RepID = rD1.RepID AND rD2.StartDate = DateAdd (Day, 1, rD1.EndDate) AND (rD2.Role = rD1.Role OR (rD2.Role IS NULL AND rD1.Role IS NULL) OR (rD2.Role = '' AND rD1.Role = ''))
UNION
SELECT rD2.RepID, rD2.Role , rD2.StartDate, rD2.EndDate
FROM repDetails rD1
INNER JOIN repDetails rD2
ON rD2.RepID = rD1.RepID AND rD2.StartDate = DateAdd (Day, 1, rD1.EndDate) AND (rD2.Role = rD1.Role OR (rD2.Role IS NULL AND rD1.Role IS NULL) OR (rD2.Role = '' AND rD1.Role = ''))
) T1
ON EP.RepID = T1.RepID AND EP.StartDate = T1.StartDate
WHERE T1.RepID IS NULL
The key here is to identify continuous rows until the role changes. This can be done by comparing the next row's role using the lead function and some additional logic to categorize all the previous rows into the same group.
After classifying them into groups, you just need to use min and max to get the start and end dates.
with groups as (
select x.*
,case when grp = 1 then 0 else 1 end + sum(grp) over(partition by repid order by startdate) grps
from (select t.*
,case when lead(role) over(partition by repid order by startdate) = role then 0 else 1 end grp
from t) x
)
select distinct repid,role
,min(startdate) over(partition by repid,grps) startdt
,max(enddate) over(partition by repid,grps) enddt
from groups
order by 1,3
Sample demo
do you just want the min(start) / max(end) dates for each repID and role?
If so, try:
Select
repID, role,
min(starDate),
max(endDate)
from
tbl
group by
repID, role
--
A more verbose solution, equivalent to VKP's:
SELECT
repid, ROLE, grpID,
MIN(startdate) AS min_startDateOverRole,
MAX(endDate) AS max_endDateOverRole
FROM
(SELECT
*, CASE WHEN isGrpEnd = 1 THEN 0 ELSE 1 end +
-- when on group end row, don't increment grpID.
-- Wait until start of next group
SUM(isGrpEnd) OVER(ORDER BY startdate) grpID
-- sum(all group end rows up to this one)
FROM
(SELECT
*,
CASE WHEN lead(ROLE) OVER(ORDER BY startdate) = ROLE
THEN 0 ELSE 1 end isGrpEnd
FROM t) x )
GROUP BY
repid, ROLE, grpid
ORDER BY
1,3
I have the following table:
What i want is the following result:
InteractionID - OpenTime - CloseTime
Opentime is the DATE_STAMP where UPDATE_TYPE = "Open" and
CloseTime is is the DATE_STAMP where UPDATE_TYPE = "Close"
I have the following SQL Query:
Select DISTINCT A.INTERACTION_ID as idd,
(Select B.DATE_STAMP from dbo.SD_INTERACTIONS_HISTORY B WHERE B.UPDATE_TYPE = 'Open' and B.INTERACTION_ID = A.INTERACTION_ID) as OpenTime,
(Select TOP 1 C.DATE_STAMP from dbo.SD_INTERACTIONS_HISTORY C WHERE C.UPDATE_TYPE = 'Close' and C.INTERACTION_ID = A.INTERACTION_ID) as CloseTime
from dbo.SD_INTERACTIONS_HISTORY A where DATEPART(year, A.DATE_STAMP) > 2014
It work kinda ok, but i have 2 questions:
Is this a correct way to do this? It seems like a slow query, so perhaps there is a way to optimize this?
Instead of checking that the datestamp is > than 2014, I would like to find the results where OpenTime is less than 30 days, how do i do this?
I am using SQL Server 2008
You can try this query
SELECT DISTINCT A.INTERACTION_ID as idd,
A.DATE_STAMP AS OpenTime,
B.DATE_STAMP AS CloseTime,
FROM dbo.SD_INTERACTIONS_HISTORY A
JOIN dbo.SD_INTERACTIONS_HISTORY B ON A.INTERACTION_ID = B.INTERACTION_ID
AND A.UPDATE_TYPE = 'Open'
AND B.UPDATE_TYPE = 'Close'
WHERE DATEDIFF(DAY,A.DATE_STAMP,GETDATE())<30
something like this?
SELECT
INTERACTION_ID,
update_open,
update_close,
datediff('d',update_open,update_close) AS diff
FROM
(SELECT
INTERACTION_ID,
MAX(CASE WHEN update_type = 'Open' THEN DATE_STAMP ELSE NULL END) AS update_open,
MAX(CASE WHEN update_type = 'Close' THEN DATE_STAMP ELSE NULL END) AS update_close
FROM
SD_INTERACTIONS_HISTORY
WHERE
DATEPART(YEAR, DATE_STAMP) > 2014 AND
UPDATE_TYPE IN('Open','Close')
GROUP BY
INTERACTION_ID) mx
WHERE
datediff('d',update_open,update_close) < 30
You can join the table with itself.
First for Open record, and join with the closed records.
SELECT
O.INTERACTION_ID,
O.DATE_STAMP DATE_STAMP_OPEN,
C.DATE_STAMP DATE_STAMP_CLOSE
FROM dbo.SD_INTERACTIONS_HISTORY O
INNER JOIN dbo.SD_INTERACTIONS_HISTORY C ON
O.INTERACTION_ID = C.INTERACTION_ID AND
O.UPDATE_TYPE = "Open" AND
C.UPDATE_TYPE = "Closed"
WHERE
O.DATE_STAMP > DATEADD(DAY,-30,GETDATE())
You can replace GETDATE with a variable if you want to define the date.
With inner join you well only get "Full records" both a Open and Close.
With Left you will get records that are still Open.
Well, you have some options now, I'll just throw one more in:
;With CTE AS
(
SELECT INTERACTION_ID,
CASE WHEN UPDATE_TYPE = 'open' THEN
DATE_STAMP
END As OpenTime,
CASE WHEN UPDATE_TYPE = 'close' THEN
DATE_STAMP
END As CloseTime
FROM SD_INTERACTIONS_HISTORY
WHERE UPDATE_TYPE IN('open', 'close')
)
SELECT INTERACTION_ID, MAX(OpenTime) As OpenTime, MAX(CloseTime) As CloseTime
FROM CTE
GROUP BY INTERACTION_ID
(Personally, I like the self join option better, but I was already writing this so...)
You can do it with some join criteria and a DATE comparison on the WHERE clause like so:
CREATE TABLE #interactions
(
id INT ,
date_stamp DATETIME ,
update_type NVARCHAR(10)
)
INSERT INTO #interactions
( id, date_stamp, update_type )
VALUES ( 1, DATEADD(DAY, -2, GETDATE()), 'Open' ),
( 1, DATEADD(DAY, -1, GETDATE()), 'Update' ),
( 1, GETDATE(), 'Close' )
SELECT DISTINCT
i.id ,
iOpen.date_stamp OpenTime ,
iClose.date_stamp CloseTime
FROM #interactions i
INNER JOIN #interactions iOpen ON iOpen.id = i.id
AND iOpen.update_type = 'Open'
INNER JOIN #interactions iClose ON iClose.id = i.id
AND iClose.update_type = 'Close'
WHERE iOpen.date_stamp >= DATEADD(DAY, -30, GETDATE())
DROP TABLE #interactions
PLease i want to return only debtorid from this T-SQL . It gives the error "
No column name was specified for column 2 of 't'." My query is below.
with t as
(SELECT debtorid,MAX(dbo.FollowUp.followupdate) FROM dbo.FollowUp WITH (NOLOCK) WHERE
( dbo.FollowUp.FollowUpDate >= '01-01-2011 00:00:00:000' and dbo.FollowUp.FollowUpDate <= '01-13-2014 23:59:59.000'
and Status = 'PTP') GROUP BY [Status], DebtorId)
SELECT t.debtorid FROM t;
WIth my little knowledge , i thought the above should work fine for me. however, it didn't.Any help would be appreciated.
You need to add a name to your second column, e.g.:
with t as
(SELECT debtorid, MAX(dbo.FollowUp.followupdate) maxFollowup
FROM dbo.FollowUp WITH (NOLOCK)
WHERE dbo.FollowUp.FollowUpDate >= '01-01-2011 00:00:00:000'
and dbo.FollowUp.FollowUpDate <= '01-13-2014 23:59:59.000'
and Status = 'PTP'
GROUP BY [Status], DebtorId)
SELECT t.debtorid FROM t;
You are using Common Table Expressions or CTE, in CTE you must have column name as per msdn. You can also refer for CTE best practices:
http://technet.microsoft.com/en-us/library/ms190766(v=sql.105).aspx
http://blog.sqlauthority.com/2011/05/10/sql-server-common-table-expression-cte-and-few-observation/
;with t as
(
SELECT FWP.debtorid
,MAX(FWP.followupdate) followupdate
FROM dbo.FollowUp FWP WITH (NOLOCK)
WHERE
(
FWP.FollowUpDate >= '01-01-2011 00:00:00:000'
and FWP.FollowUpDate <= '01-13-2014 23:59:59.000'
and FWP.Status = 'PTP'
) GROUP BY FWP.[Status], FWP.DebtorId
)
SELECT t.debtorid FROM t;