I am working on a report and need to report hours per employee.
However, some people worked longer than Max Hours and a simple sum will not work in the following case...
I tried to use the Min Function but it only works as column level...
I saw =calculation function should work but I am not sure how to write it... below is the example:
Staff ID Date Work Hours
A001 5-Jan-2015 8
A001 6-Jan-2015 8
A001 7-Jan-2015 8
A001 8-Jan-2015 8
A001 9-Jan-2015 8
A002 5-Jan-2015 7
A002 6-Jan-2015 7
A002 7-Jan-2015 6
A002 8-Jan-2015 7
A002 9-Jan-2015 6
Staff ID Staff Name Max Hours Per Week
A001 Person A 35
A002 Person B 35
Output:
Staff ID Hours
A001 35 (instead of 40)
A002 33 (7+7+6+7+6)
Thanks a lot for your help!
Start with a Measure called hours that simply sums the column:
=SUM(Table1[Work Hours])
This measure then uses that sum and does an IF() to check whether the person is over the limit and returns the appropriate number. The SUMX() iterates over each person in order to give you a correct total.
=
SUMX (
VALUES ( Table1[Staff ID] ),
IF (
[Hours] > VALUES ( Table2[Max Hours Per Week] ),
VALUES ( Table2[Max Hours Per Week] ),
[Hours]
)
)
Assumes you have 2 tables called table1 and 2 that are related on Staff ID.
Related
The Data:
I have a table, BaseTable that is a daily snapshot table. It has four columns, SnapshotDate, RequestId, EmployeeId, and Status. It is a table of each Request Id and their status every day (either active or inactive) and which employee is assigned to it. The Employee assigned can and does change over time.
What I am trying to accomplish:
I am trying to write a query that will calculate the number of days a Request was inactive, however, the tricky part is that it should not start counting until after an EmployeeId has been assigned to the request and therefore it should count differently for each Employee. For example, if Employee 1 and 2 were each assigned to Request Id 908, Employee 1 was assigned on Jan 1st 2022 and Employee 2 took over on Feb 1st 2022 then Employee 2 will have a smaller number showing for the number of days the request was inactive (a month less since he started a month later). The output of the query if it was run on 2022-05-01 (May 1st) would look like the following:
RequestId
EmployeeId
EmployeeAssignedDate
DaysInactive
908
1
2022-01-01
120
908
2
2022-02-01
89
732
4
2022-03-01
61
732
1
2022-04-01
30
732
3
2022-05-01
0
What I've done so far:
Using the BaseTable I created a table EmployeeDates that shows the distinct RequestId, EmployeeId, and EmployeeAssignedDate:
EmployeeDates AS (
SELECT
RequestId,
EmployeeId,
Min(SnapshotDate) AS EmployeeAssignedDate,
FROM
BaseTable
GROUP BY 1, 2
)
The next thing I tried was the query below but it did not correctly start counting after each assigned date, the output was that it showed the number of days inactive per RequestId and completely ignored the EmplyeeAssignedDates. Meaning in the above example instead of showing 120 days, and 89 days in 1st and 2nd rows respectively, it showed 120 days for both and in rows 3,4,and 5 it showed 61 days.
SELECT
ed.RequestId,
ed.EmployeeId,
ed.EmployeeAssignedDate,
SUM(IF(bt.Status = 'inactive'
AND bt.SourcingRequestSnapshotDate >= ed.EmployeeAssignedDate, 1, 0))
AS DaysInactive
FROM
EmployeeDates ed
LEFT JOIN
BaseTable bt
ON
ed.RequestId = bt.RequestId
GROUP BY
1, 2, 3
If anyone knows a method of how to calculate what I'm looking for I would really appreciate the help.
I have a table with couple of customers resided in a hotel for a month or months. I need to find 3 most visited hotels by month. In case one customer lived in a hotel for three months, then it refers for three month. To be more precise below table hotel I have:
id
usr_id
srch_ci
srch_co
hotel_id
1
13
2021-10-01
2021-11-22
200
2
12
2021-10-11
2021-10-22
300
3
11
2021-10-28
2021-11-05
200
4
10
2021-10-28
2021-12-03
100
Result should look like below:
mnth
hotel_id
rnk
visits
2021-10
200
1
2
2021-10
100
2
1
2021-10
300
2
1
2021-11
200
1
2
2021-11
100
2
1
2021-12
100
1
1
As we can see above, user_id = 10 stayed in a hotel = 100 for 3 different months. That means it is counted for 3 different month for a hotel as 1 count. And for 2021-12 month only user = 10 stayed, for this reason in 2021-12 month hotel = 100 is ranked as 1st.
I solved problem using generate_series function in Postgres. That is what I was looking for. This link helped me. Splitting single row into multiple rows based on date
SELECT hotel_id,mnth,visits,
ROW_NUMBER() OVER (PARTITION BY mnth ORDER BY visits DESC) AS rnk FROM (
SELECT hotel_id,to_char(live_mnth,'YYYY-MM') AS mnth,count(*) AS visits FROM (
SELECT id,usr_id,hotel_id,date_in,date_out,
generate_series(date_in, date_out, '1 MONTH')::DATE AS live_mnth
FROM (
SELECT *,TO_CHAR(srch_ci, 'yyyy-mm-01')::date AS date_in,
TO_CHAR(srch_co, 'yyyy-mm-01')::date AS date_out
FROM hotels
) s
) s GROUP BY hotel_id,to_char(live_mnth,'YYYY-MM')
) t
I'd like to find out how many days in a week users have visited my site. For example, 1 day in a week, 2 days in a week, every day of the week (7).
I imagine the easiest way of doing this would be to set the date range and find out the number of days within that range (option 1). However, ideally I'd like the code to understand a week so I can run a number of weeks in one query (option 2). I'd like the users to be unique for each number of days (ie those who have visited 2 days have also visited 1 day but would only be counted in the 2 days row)
In my database (using SQLWorkbench64) I have user ids (id) and date (dt)
I'm relatively new to SQL so any help would be very much appreciated!!
Expected results (based on total users = 5540):
Option 1:
Number of Days Users
1 2000
2 1400
3 1000
4 700
5 300
6 100
7 40
Option 2:
Week Commencing Number of Days Users
06/05/2019 1 2000
06/05/2019 2 1400
06/05/2019 3 1000
06/05/2019 4 700
06/05/2019 5 300
06/05/2019 6 100
06/05/2019 7 40
You can find visitor count between a date range with below script. Its also consider if a visitor visits multi days in the given date range, s/he will be counted for the latest date only from the range-
Note: Dates are used as sample in the query.
SELECT date,COUNT(id)
FROM
(
SELECT id,max(date) date
FROM your_table
WHERE date BETWEEN '04/21/2019' AND '04/22/2019'
GROUP BY ID
)A
GROUP BY date
You can find the Monday of the week of a date and then group by that. After you have the week day there is a series of group by. Here is how I did this:
DECLARE #table TABLE
(
id INT,
date DATETIME,
MondayOfWeek DATETIME
)
DECLARE #info TABLE
(
CommencingWeek DATETIME,
NumberOfDays INT,
Users INT
)
INSERT INTO #table (id,date) VALUES
(1,'04/15/2019'), (2,'07/21/2018'), (3,'04/16/2019'), (4,'04/16/2018'), (1,'04/16/2019'), (2,'04/17/2019')
UPDATE #table
SET MondayOfWeek = CONVERT(varchar(50), (DATEADD(dd, ##DATEFIRST - DATEPART(dw, date) - 6, date)), 101)
INSERT INTO #info (CommencingWeek,NumberOfDays)
SELECT MondayOfWeek, NumberDaysInWeek FROM
(
SELECT id,MondayOfWeek,COUNT(*) AS NumberDaysInWeek FROM #table
GROUP BY id,MondayOfWeek
) T1
SELECT CommencingWeek,NumberOfDays,COUNT(*) AS Users FROM #info
GROUP BY CommencingWeek,NumberOfDays
ORDER BY CommencingWeek DESC
Here is the output from my query:
CommencingWeek NumberOfDays Users
2019-04-14 00:00:00.000 1 2
2019-04-14 00:00:00.000 2 1
2018-07-15 00:00:00.000 1 1
2018-04-15 00:00:00.000 1 1
I have a database that has RMA return data. I want to write a query to return the total number of times a unit has been returned (each return has a unique RMA Number). I also need to return the number of times a unit has returned multiple times, and the number of times it returned for the same symptom. A record is created each time the unit goes to a station (RMA, symptom, and date returned is propagated for each station record).
The data looks like this:
ID SN RMA SYMPTOM Station Date_Returned
21567 A001 84704 POWER FAULT DockRecv 01/01/2015
21568 A001 84704 POWER FAULT Repair 01/01/2015
21569 A001 84704 POWER FAULT Ship 01/01/2015
10235 A002 83494 NO DISPLAY DockRecv 02/20/2015
10236 A002 83494 NO DISPLAY Repair 02/20/2015
10237 A002 83494 NO DISPLAY Ship 02/20/2015
36548 A002 84283 ABNORMAL NOISE DockRecv 10/05/2015
36549 A002 84283 ABNORMAL NOISE Repair 10/05/2015
36550 A002 84283 ABNORMAL NOISE Ship 10/05/2015
38790 A003 83432 HDD FAULT DockRecv 09/15/2015
38791 A003 83432 HDD FAULT Repair 09/15/2015
38792 A003 83432 HDD FAULT Ship 09/15/2015
69613 A003 84276 HDD FAULT DockRecv 01/30/2016
69614 A003 84276 HDD FAULT Repair 01/30/2016
69615 A003 84276 HDD FAULT Ship 01/30/2016
56732 A004 82011 NFF DockRecv 12/01/2015
56733 A004 82011 NFF Repair 12/01/2015
56734 A004 82011 NFF Ship 12/01/2015
My Output needs to look like this:
Total_Returns Repeat_Return Same_Symptom_Return
6 2 1
A001(RMA 84704) is a single return.
A002 is a multiple return-(RMA 83494) is the first return (after repaired, the unit is shipped out) after some time in the field, the unit is returned again A002(RMA 84283).... When a unit is returned, it goes through 3 stations (we create a record for each station (propagating the RMA, symptom, and date returned for each station record).
I can get Total_Returns with the code:
Select count(*) as totalcount
From
(
SELECT
[SN]
,[RMA]
FROM [dbo].[test]
Group by [SN],[RMA]
)as a
There are 3 quite different methods needed to arrive at the counts, so I have used 3 separate sub-queries. see this working at sqlfiddle (but not on MS SQL Server) here: http://sqlfiddle.com/#!5/9df16/1
Result:
| Total_Count | Repeat_Return | Same_Symptom_Return |
|-------------|---------------|---------------------|
| 6 | 2 | 1 |
Query:
select
(select count(distinct SN + RMA + SYMPTOM) from table1) as Total_Count
, (select count(*) from(
SELECT SN
FROM table1
Group by SN
having count(distinct Date_Returned) > 1)
) as Repeat_Return
, (select count(*) from(
SELECT SYMPTOM
FROM table1
Group by SYMPTOM
having count(*)/3 > 1)
) as Same_Symptom_Return
note: you should include "sql server" as a tag on your question (well I presum it is that because of the [dbo].[test]
I got it to work... I'm sure there is a more streamline way to write it...
SELECT
-- Get Total_Returned Count
(Select distinct
count(*) as 'Total_Returned'
From
( SELECT
[SN]
,[RMA]
FROM [dbo].[test]
Group by [SN],[RMA]
)a) AS 'Total_Returned'
-- Get Repeat_Return Count
,(Select distinct
[Repeat_Return] - COUNT(*) OVER() AS [Repeat_Return]
From
( SELECT
COUNT(*) OVER() AS [Repeat_Return]
,[SN]
,[RMA]
FROM [dbo].[test]
Group by [SN],[RMA]
)a Group by [SN],[Repeat_Return]) AS 'Repeat_Return'
-- Get Same_Symptom_Return Count
,(Select distinct
[Same_Symptom_Return] - COUNT(*) OVER() AS [Same_Symptom_Return]
From
( SELECT
COUNT(*) OVER() AS [Same_Symptom_Return]
,[SN]
,[RMA]
,SYMPTOM
FROM [dbo].[test]
Group by SN, SYMPTOM, RMA
)a Group by [SN], SYMPTOM, [Same_Symptom_Return]) AS 'Same_Symptom_Return'
Result:
|Total_Returned | Repeat_Return | Same_Symptom_Return |
|---------------|---------------|---------------------|
| 6 | 2 | 1 |
I would like to find the percent of repeat visitors to my site. Currently I am selecting users for one month and dividing that month by the following month. to calculate those that have returned. Is this the best way to write that query?
it is yielding results that seem to be accurate, but wondering if there is a more elegant solution.
SELECT (
SELECT COUNT(table.user) as Total
FROM table
WHERE table.event IN ('event1','event2','event3')
AND table.month IN ('october')
) /
(
SELECT COUNT(table.user) as newTotal
FROM table
WHERE table.event IN ('event1','event2','event3')
AND (table.month IN ('october') OR table.month IN ('november'))
) AS percent_return
table structure looks like this, you have the same user purchasing multiple events for the same month or the same time period.
order_number user month event gross
1 jack october event2 30
2 jack november event3 20
3 jack november event3 20
4 jack november event2 30
5 sam november event2 30
6 john october event3 20
7 john october non_event 20
You don't need two subqueries to do what you want. Just use conditional aggregation:
SELECT (SUM(s.month IN (october)) / SUM(s.month IN (october, november))
) as percent_return
FROM sales s
WHERE s.event IN ('event1', 'event2', 'event3') AND
s.gross > 0;
Also, there is no need for single quotes around numeric constants.