Confusing sum result - sql

I've 3 tables as below.
Users
StatusTable
Time_Tracker
And the relation is as below.
users have username and userid, StatusTable has userName and Time_Tracker has userName
Below is my table Data.
And here I'm trying to get the sum
Problem:
I want to update the productiontime as sum of time taken[minutes] by joining case owner to username and TT.userId = Users.userId and the login = GetDate()
My Query is
update Time_Tracker set ProductionTime = (select sum(ST.[time taken(minutes)])
from statustable as st inner join users as u
on st.[case owner] = u.username
inner join Time_Tracker as TT
on u.userId = TT.userId
where cast(st.[Start Time] AS DATE) = CAST(GETDATE() as Date)
Group By TT.UserId, u.UserId) where CAST(Login AS DATE) = CAST(GETDATE() as Date)
And the blue box in my image is my current O/p.
When I run
select sum([time taken(minutes)]) as totalTme from StatusTable where cast([Start Time] AS DATE) = CAST(GETDATE() as Date)
I get the O/p as 2.05 which is correct one.
please let me know where am I going wrong in my first query(printing 10.25) instead of 2.05.
How can I fix this.
Thanks

I think you have too many joins in the subquery:
update Time_Tracker tt
set ProductionTime = (select sum(ST.[time taken(minutes)])
from statustable st inner join
users u
on st.[case owner] = u.username
where u.userId = tt.userId and
cast(st.[Start Time] AS DATE) = CAST(GETDATE() as Date)
)
where CAST(Login AS DATE) = CAST(GETDATE() as Date);
Your version is multiplying the result for each row in TimeTracker. The correlation clause is what you need.
Also very important. Such a correlated subquery should not have a GROUP BY clause. The GROUP BY could return multiple rows, but by definition the correlated subquery should return at most one row.

Related

Converting an AVG from HH-MM-SS to Minutes

I have a query like this:
with first_reply as (
select
t.id as ticket_id,
tc.created,
row_number() over(partition by tc.ticket_id order by tc.created) as rn
from ticket t
inner join ticket_comment tc
on t.id = tc.ticket_id
inner join user u
on u.id = tc.user_id
where u.role in ('employee')
order by tc.ticket_id, tc.created)
select
avg(far.created-t.created_at)
from ticket t
inner join first_agent_reply far
on far.ticket_id = t.id
join ticket_tag tt
ON tt.ticket_id = t.id
AND rn = 1
It gives me an avg time in the format of 22:23:56.973609
How can I convert this to showing me just total minutes? Ie: 1920 Mins
Thank you!
If you're using sql server please use the below function,
DATEDIFF(minute, 0, CONVERT(TIME,'22:23:56.973609'))
Probably the last part of your code will be like this,
select
DATEDIFF(minute, 0, CONVERT(TIME,avg(far.created-t.created_at)))
from ticket t
The answer you get here is 1343

How to convert rows in columns

I have some problems with a SQL query, I try to convert row in columns.
select U.FirstName,U.LastName,Sh.[Day],Sh.StartTime,Sh.EndTime from dbo.[User] as U
inner join dbo.Employee as E on U.UserId = E.UserId
inner join dbo.ScheduleStaff as SH on SH.EmployeeId = E.EmployeeId
where ((Sh.[Day] < getdate()+ 4 ) and sh.[Day] >= getdate())
group by U.FirstName, U.LastName,Sh.[Day],Sh.StartTime,Sh.EndTime
This query gives me the below result:
How can I make that there is one employee per line, and the days turn into columns?
I try this:
select FirstName,LastName,Day1,Day2,Day3
from
(
select U.FirstName,U.LastName,Sh.[Day],Sh.StartTime,Sh.EndTime,concat('Day',ROW_NUMBER() over (partition by
U.FirstName,U.LastName order by U.FirstName,U.LastName)) as Tests
from dbo.[User] as U
inner join dbo.Employee as E on U.UserId = E.UserId
inner join dbo.ScheduleStaff as SH on SH.EmployeeId = E.EmployeeId
where ((Sh.[Day] < getdate()+ 4 ) and sh.[Day] >= getdate()-1)
group by U.FirstName, U.LastName,Sh.[Day],Sh.StartTime,Sh.EndTime
)Temp
pivot
(
Max([Day])
for Tests in (Day1,Day2,Day3)
)Piv
But this is not exactly what I need, how can I make the days as columns and their time as values?
This will work if you have static [Date] value. But if you want [Date] dynamic then you need to collect date value and put into pivot section.
Your question was[how can I make the days as columns and their time as values]
select FirstName,LastName,[2020-08-28],[2020-08-29] from
(select FirstName,LastName,[Date], CONCAT(StartTime,'-to-'+EndTime) as [Time] from tbl_user) t
pivot(MAX(t.[Time]) for [Date] in([2020-08-28],[2020-08-29]) )pvt
Note: for dynamic date value. You can follow Terence link mentioned in comment section.

SQL : Get Column table twice with differents clause where

I try to get the same column in the same table twice with different clauses :
My query:
SELECT
*
FROM
(SELECT TOP 10
CONVERT(DATE, attemptdate) AS Date,
Max(currentcount) AS A
FROM
logintracking
INNER JOIN
maxuser ON logintracking.loginid = maxuser.loginid
INNER JOIN
site ON site.siteid = maxuser.defsite
WHERE
attemptdate BETWEEN #dateDebut AND #dateFin
AND logintracking.clientaddr IN ('10.118.254.21', '10.118.254.156')
GROUP BY
CONVERT(DATE, attemptdate)
ORDER BY
CONVERT(DATE, attemptdate) ASC
) AS T1,
(SELECT TOP 10
CONVERT(DATE, attemptdate) AS Date,
MAX(currentcount) AS B
FROM
logintracking
INNER JOIN
maxuser ON logintracking.loginid = maxuser.loginid
INNER JOIN
site ON site.siteid = maxuser.defsite
WHERE
attemptdate BETWEEN #dateDebut AND #dateFin
AND logintracking.clientaddr = '10.118.254.35'
GROUP BY
CONVERT(DATE, attemptdate)
ORDER BY
CONVERT(DATE, attemptdate) ASC) AS T2
Result:
Desired result:
My objective is to get the same column 'max(currentcount)' twice and to apply different where clauses so to get two columns named (A & B), and i need also to show the date in the first column, can you please help ? Thanks
Since the only difference between A and B is logintracking.clientaddr, you can put that condition within a CASE statement within the MAX function:
SELECT CONVERT(DATE, attemptdate) AS Date,
MAX(CASE WHEN logintracking.clientaddr IN ( '10.118.254.21', '10.118.254.156' ) THEN currentcount END) AS A,
MAX(CASE WHEN logintracking.clientaddr IN ( '10.118.254.35' ) THEN currentcount END) AS B
FROM logintracking
INNER JOIN maxuser
ON logintracking.loginid = maxuser.loginid
INNER JOIN site
ON site.siteid = maxuser.defsite
WHERE attemptdate BETWEEN #dateDebut AND #dateFin
GROUP BY CONVERT(DATE, attemptdate)
ORDER BY CONVERT(DATE, attemptdate) ASC

How to use Select query with MAX Date?

I am trying to get latest Date from Database.But getting query error on 'Reservation.EntryDate'
Select Rooms.RoomTitle,Rooms.IsReserved,Reservation.CheckInTime,Reservation.CheckOutTime
From Reservation,Rooms
INNER JOIN
(SELECT Reservation.RoomID, MAX(Reservation.EntryDate) AS MaxDateTime
FROM Reservation
GROUP BY Reservation.RoomID) groupedtt
ON Rooms.RoomID = groupedtt.RoomID
AND Reservation.EntryDate = groupedtt.MaxDateTime
What am I doing wrong?
Don't mix implicit and explicit join syntax
Select ro.RoomTitle,
ro.IsReserved,
res.CheckInTime,
res.CheckOutTime
From Reservation res
join Rooms ro ON ro.RoomID = res.RoomID
join
(
SELECT RoomID, MAX(EntryDate) AS MaxDateTime
FROM Reservation
GROUP BY RoomID
) groupedtt ON ro.RoomID = groupedtt.RoomID
AND res.EntryDate = groupedtt.MaxDateTime

Combining two counts with joins in one query

Ok - hoping someone can help as I'm struggling here. Have tried using sum(case when), count(*), subqueries with no success.
Essentially I have two queries I am trying to combine into one, grouped by the same parameter. The queries:
Query 1:
SELECT
u.username,
count(*) as 'Total'
FROM log1 L1
JOIN users u on u.userref = L1.userref
WHERE L1.date between #FromDate and #ToDate
GROUP BY u.username
ORDER BY u.username
Query 2:
SELECT
u.username,
count(*) as 'Total'
FROM log2 L2
LEFT JOIN users u on u.userref = L2.userref
WHERE L2.date between #FromDate and #ToDate and L2.message like '%None%'
GROUP BY u.username
ORDER BY u.username
What I would like is a single query with a username column (u.username), a column showing the results of query 1, and a column showing the results of query two. Any help appreciated!
You can put a case statement inside the count function to only count when certain criteria is met:
SELECT u.username,
Total = COUNT(*),
Total2 = COUNT(CASE WHEN L.message LIKE '%None%' THEN 1 END)
FROM log1 AS L
JOIN users AS u
ON u.userref = L.userref
WHERE L.date BETWEEN #FromDate and #ToDate
GROUP BY u.username
ORDER BY u.username;
Of note:
BETWEEN can cause problems, especially when working with dates
Using string literals for column aliases is on the deprecation list
EDIT
Completely missed that you had two separate log tables:
SELECT u.username,
Total = COUNT(Count1),
Total2 = COUNT(Count2)
FROM ( SELECT l.UserRef, Count1 = 1, Count2 = NULL
FROM log1 AS L
WHERE L.date BETWEEN #FromDate and #ToDate
UNION ALL
SELECT l.UserRef, Count1 = NULL, Count2 = 1
FROM log2 AS L
WHERE L.date BETWEEN #FromDate and #ToDate
AND L.message LIKE '%None%'
) AS l
JOIN users AS u
ON u.userref = L.userref
GROUP BY u.username
ORDER BY u.username;
SELECT X.USERNAME,X.TOTAL,Y.TOTAL
FROM(SELECT
u.username,
count(*) as 'Total'
FROM log1 L1
JOIN users u on u.userref = L1.userref
WHERE L1.date between #FromDate and #ToDate
GROUP BY u.username
) as x
INNER JOIN
(
SELECT
u.username,
count(*) as 'Total'
FROM log2 L2
LEFT JOIN users u on u.userref = L2.userref
WHERE L2.date between #FromDate and #ToDate and L2.message like '%None%'
GROUP BY u.username
) AS Y ON Y.USERNAME = X.USERNAME