I have a table that looks like this:
**ActivityNumber -- TimeStamp -- PreviousActivityNumber -- Team**
1234-4 -- 01/01/2017 14:12 -- 1234-3 -- Team A
There are 400,000 rows.
The ActivityNumber is a unique ticket number with the activity count attached. There are 4 teams.
Each activitynumber is in the table.
I need to calculate the average time taken between updates for each team, for each month (to see how each team is improving over time).
I produced a query which counts the number of activities per team per month - so I'm part way there.
I'm unable to find the timestamp for the previousActivityNumber so I can subtract it from the current Activity number. If I could get this, I could run an average on it.
Conceptually:
select a1.Team,
a1.ActivityNumber,
a1.TimeStamp,
a2.Timestamp as PrevTime,
datediff('n',a1.Timestamp, a2.timestamp) as WorkMinutes
from MyTable a1
left join MyTable a2
on ((a1.Team = a2.Team)
and (a1.PreviousActivityNumber = a2.ActivityNumber )
Related
I have table like below:
I have to calculate daily average count of session for each user.
First i calculated, total no of sessions for each day for every user and from that i tried to calculate average of daily session. I understand that it wont work since all users dont have sessions for every date.Some dates are missing for all users. Is there any way to calculate daily average when there is no entries for some dates
WITH daily_count AS
(
SELECT user_id, to_char(local_time,’MM/DD/YYYY’) AS Date, count(session_id) AS total_count
FROM table_name
GROUP BY device_id, to_char(local_time,’MM/DD/YYYY’)
)
SELECT user_id , AVG(total_count) AS average_session_count
FROM daily_count
GROUP BY user_id
For eg: The max date in the above given table is Feb04 and the min date is Jan31 .So the total no of days is 5 days.If we take Userid 1, it is having records only for 2 dates. So the query i wrote will calculate average for 2 days not for 5 days. How to make it to calculate average for 5 days
if for date 1,2,3 number of sessions for one user is 1,0(no sessions),5 then what output do you want in average sessions? --> 2 or 3?
You need to change your main query as follows:
SELECT USER_ID,
AVG(TOTAL_COUNT) AS AVERAGE_SESSION_COUNT -- if you want output as 3 then use this
--SUM(TOTAL_COUNT)/(MAX(DATE) - MIN(DATE) + 1) -- if you want output as 2 then use this
FROM DAILY_COUNT
GROUP BY USER_ID
I have two tables. One is NAV where product daily new price is updated. Second is TDK table where item wise stock is available.
Now I want to get a summery report as per buyer name where all product wise total will come and from table one latest price will come.
I have tried below query...
SELECT dbo.TDK.buyer, dbo.NAV.Product_Name, sum(dbo.TDK.TD_UNITS) as Units, sum(dbo.TDK.TD_AMT) as 'Amount',dbo.NAV.NAValue
FROM dbo.TDK INNER JOIN
dbo.NAV
ON dbo.TDK.Products = dbo.NAV.Product_Name
group by dbo.TDK.buyer, dbo.NAV.Product_Name, dbo.NAV.NAValue
Imnportant: Common columns in both tables...
Table one NAV has column as Products
Table two TDK has column as Product_Name
If I have NAValue 4 records for one product then this query shows 4 lines with same total.
What I need??
I want this query to show only one line with latest NAValue price.
I want display one more line with Units*NAValue (latest) as "Latest Market Value".
Please guide.
What field contains the quote date? I am assuming you have a DATIME field, quoteDate, in dbo.NAV table and my other assumption is that you only store the Date part (i.e. mid-night, time = 00:00:00).
SELECT
t.buyer,
n.Product_Name,
sum(t.TD_UNITS) as Units,
sum(t.TD_AMT) as 'Amount',
n.NAValue
FROM dbo.TDK t
INNER JOIN dbo.NAV n
ON t.Products = n.Product_Name
AND n.quoteDate > getdate()-2
group by t.buyer, n.Product_Name, n.NAValue, n.QuoteDate
GetDate() will give you the current date and time. Subtracting 2 would get it before yesterday but after the day before yesterday.
Also, add n.quoteDate in your select and group by. Even though you don't need it, in case that one day you have a day of bad data with double record in NAV table, one with midnight time and another with 6 PM time.
Your code looks like SQL Server. I think you just want APPLY:
SELECT t.buyer, n.Product_Name, t.TD_UNITS as Units, t.TD_AMT as Amount, n.NAValue
FROM dbo.TDK t CROSS APPLY
(SELECT TOP (1) n.*
FROM dbo.NAV n
WHERE t.Products = n.Product_Name
ORDER BY ?? DESC -- however you define "latest"
) n;
I am looking for some general advice rather than a solution. My problem is that I have a list of dates per person where due to administrative procedures, a person may have multiple records stored for this one instance, yet the date recorded is when the data was entered in as this person is passed through the paper trail. I understand this is quite difficult to explain so I'll give an example:
Person Date Audit
------ ---- -----
1 2000-01-01 A
1 2000-01-01 B
1 2000-01-02 C
1 2003-04-01 A
1 2003-04-03 A
where I want to know how many valid records a person has by removing annoying audits that have recorded the date as the day the data was entered, rather than the date the person first arrives in the dataset. So for the above person I am only interested in:
Person Date Audit
------ ---- -----
1 2000-01-01 A
1 2003-04-01 A
what makes this problem difficult is that I do not have the luxury of an audit column (the audit column here is just to present how to data is collected). I merely have dates. So one way where I could crudely count real events (and remove repeat audit data) is to look at individual weeks within a persons' history and if a record(s) exists for a given week, add 1 to my counter. This way even though there are multiple records split over a few days, I am only counting the succession of dates as one record (which after all I am counting by date).
So does anyone know of any db2 functions that could help me solve this problem?
If you can live with standard weeks it's pretty simple:
select
person, year(dt), week(dt), min(dt), min(audit)
from
blah
group by
person, year(dt), week(dt)
If you need seven-day ranges starting with the first date you'd need to generate your own week numbers, a calendar of sorts, e.g. like so:
with minmax(mindt, maxdt) as ( -- date range of the "calendar"
select min(dt), max(dt)
from blah
),
cal(dt,i) as ( -- fill the range with every date, count days
select mindt, 0
from minmax
union all
select dt+1 day , i+1
from cal
where dt < (select maxdt from minmax) and i < 100000
)
select
person, year(blah.dt), wk, min(blah.dt), min(audit)
from
(select dt, int(i/7)+1 as wk from cal) t -- generate week numbers
inner join
blah
on t.dt = blah.dt
group by person, year(blah.dt), wk
I am trying find employees that worked during a specific time period and the hours they worked during that time period. My query has to join the employee table that has employee id as pk and uses effective_date and expiration_date as time measures for the employee's position to the timekeeping table that has a pay period id number as pk and also uses effective and expiration dates.
The problem with the expiration date in the employee table is that if the employee is currently employed then the date is '12/31/9999'. I am looking for employees that worked in a certain year and current employees as well as the hours they worked separated by pay periods.
When I take this condition in account in the where with an OR statement, I get duplicates that is employees that have worked the time period I am looking for and beyond as well as duplicate records for the '12/31/9999' and the valid employee in that time period.
This is the query I am using:
SELECT
J.EMPL_ID
,J.DEPT
,J.UNIT
,J.LAST_NM
,J.FIRST_NM
,J.TITLE
,J.EFF_DT
,J.EXP_DT
,TM1.PPRD_ID
,TM1.EMPL_ID
,TM1.EXP_DT
,TM1.EFF_DT
--PULLING IN THE DAILY HRS WORKED
,(SELECT NVL(SUM(((to_number(SUBSTR(TI.DAY_1, 1
,INSTR(TI.DAY_1, ':', 1, 1)-1),99))*60)+
(TO_NUMBER(SUBSTR(TI.DAY_1
,INSTR(TI.DAY_1,':', -1, 1)+1),99))),0)
FROM PPRD_LINE TI
WHERE
TI.PPRD_ID=TM1.PPRD_ID
) "DAY1"
---AND THE REST OF THE DAYS FOR THE WORK PERIOD
FROM PPRD_LINE TM1
JOIN EMPL J ON TM1.EMPL_ID=J.EMPL_ID
WHERE
J.EMPL_ID='some id number' --for test purposes, will need to break down to depts-
AND
J.EFF_DT >=TO_DATE('1/1/2012','MM/DD/YYYY')
AND
(
J.EXP_DT<=TO_DATE('12/31/2012','MM/DD/YYYY')
OR
J.EXP_DT=TO_DATE('12/31/9999','MM/DD/YYYY') --I think the problem might be here???
)
GROUP BY
J.EMPL_ID
,J.DEPT
,J.UNIT
,J.LAST_NM
,J.FIRST_NM
,J.TITLE
,J.EFF_DT
,J.EXP_DT
,TM1.PPRD_ID
,TM1.EMPL_ID
,TM1.DOC_ID
,TM1.EXP_DT
,TM1.EFF_DT
ORDER BY
J.EFF_DT
,TM1.EFF_DT
,TM1.EXP_DT
I'm pretty sure I'm missing something simple but at this point I can't see the forest for the trees. Can anyone out there point me in the right direction?
an example of the duplicate records:
for employee 1 for the year of 2012:
Empl_ID Dept Unit Last First Title Eff Date Exp Date PPRD ID Empl_ID
00001 04 012 Babbage Charles Somejob 4/1/2012 10/15/2012 0407123 00001
Exp Date_1 Eff Date_1
4/15/2012 4/1/2012
this record repeats 3 times and goes past the pay periods in 2012 to the current pay period in 2013
the subquery I use to convert time to be able to add hrs and mins together to compare down the line.
I'm going to take a wild guess and see if this is what you want, remember I could not test so there may be typos.
If this is and especially if it is not, you should read in the FAQ about how to ask good questions. If this is what you were trying to understand your question should have been answered within about 10 mins. Because it was not clear what you were asking no one could answer your question.
You should include inputs and outputs and EXPECTED output in your question. The data you gave was not the output of the select statement (it did not have the DAY1 column).
SELECT
J.EMPL_ID
,J.DEPT
,J.UNIT
,J.LAST_NM
,J.FIRST_NM
,J.TITLE
,J.EFF_DT
,J.EXP_DT
,TM1.PPRD_ID
,TM1.EMPL_ID
-- ,TM1.EXP_DT Can't have these if you are summing accross multiple records.
-- ,TM1.EFF_DT
--PULLING IN THE DAILY HRS WORKED
,NVL(SUM(((to_number(SUBSTR(TM1.DAY_1, 1,INSTR(TM1.DAY_1, ':', 1, 1)-1),99))*60)+
(TO_NUMBER(SUBSTR(TM1.DAY_1,INSTR(TM1.DAY_1,':', -1, 1)+1),99))),0)
"DAY1"
---AND THE REST OF THE DAYS FOR THE WORK PERIOD
FROM PPRD_LINE TM1
JOIN EMPL J ON TM1.EMPL_ID=J.EMPL_ID
WHERE
J.EMPL_ID='some id number' --for test purposes, will need to break down to depts-
AND J.EFF_DT >=TO_DATE('1/1/2012','MM/DD/YYYY')
AND(J.EXP_DT<=TO_DATE('12/31/2012','MM/DD/YYYY') OR J.EXP_DT=TO_DATE('12/31/9999','MM/DD/YYYY'))
GROUP BY
J.EMPL_ID
,J.DEPT
,J.UNIT
,J.LAST_NM
,J.FIRST_NM
,J.TITLE
,TM1.PPRD_ID
,TM1.EMPL_ID
,TM1.DOC_ID
ORDER BY
MIN(J.EFF_DT)
,MAX(TM1.EFF_DT)
,MAX(TM1.EXP_DT)
I would like to thank in advance for any help.
My problem relates to two tables in MySQL (Now switching to postgresql). The tables are related to a ticketing database.
a) booking. It has four columns ccode,date,time,amount
b) account It has three columns ccode,date,amount
The booking table has ticket bookings and account table has advances and payments received.
I have to prepare a statement of account based on ccode (customer code).
The statement shows columns as below
*Ccode Type Date time amount balance*
- the report in sorted on ccode and then on date (account table row appears first)
- Type column displays B or A depending on record type
- Time column is present only in booking table
- Report has a running balance for each row
- At the end for a customercode, the totals of amount and balance is displayed
I have had success, so far in creating a join as below. (and after dicussion below, have been able to generate TYPE column using IF)
SELECT booking.cname, booking.bdate, booking.btime, booking.rate, booking.ID,
IF(booking.btime IS NOT NULL, "B", "A") AS type, account.cname, account.date,
account.amount, account.ID
FROM booking
LEFT JOIN account ON booking.bdate = account.date AND booking.cname=account.cname AND
booking.rate = account.amount
UNION
SELECT booking.cname, booking.bdate, booking.btime, booking.rate, booking.ID,
IF(booking.btime IS NOT NULL, "B", "A") AS type, account.cname, account.date,
account.amount, account.ID
FROM booking
RIGHT JOIN account ON booking.bdate = account.date AND booking.cname=account.cname AND
booking.rate = account.amount
It displays all the records. A report can be generated using this table.
But is there a way to display the formatted report just by SQL.
I can change the order of columns and even add or remove existing ones as long as Record type is known and a running balance is displayed against each record.
A SAMPLE REPORT ---- REPORT A
CODE DATE TYPE AMOUNT BALANCE TIME
A1 02/19/2011 A 50 50
A1 02/20/2011 B 35 15 1230
A1 02/21/2011 A 40 55
A1 02/21/2011 B 20 35 1830
optional > TOTAL Account = 90 Booking = 55 Balance = 35
A SAMPLE REPORT ---- REPORT B
CODE AMOUNT BOOKED AMOUNT PAID BALANCE
A1 50 50 0
A1 35 15 20
A1 40 55 -15
A1 20 35 -15
this is a weekly statement version of REPORT A.
the reason is i can add where and between to get only records in a given week.
and since it is a weekly report, running balance is just omitted.
It is report grouped for all entries with customercode A1 present
in booking and account tables.
thanx
Since your data is not normalized for this, you pay the price in query complexity, as shown below:
SELECT ccode, date, time, type, amount,
(SELECT SUM(amount) AS balance
FROM numbered AS n
WHERE numbered.rownum <= n.rownum AND numbered.ccode = n.ccode) AS balance
FROM (SELECT sorted.*, #rownum := #rownum + 1 AS rownum
FROM (SELECT *
FROM (SELECT ccode, date, time, 'B' AS type, amount
FROM booking
UNION
SELECT ccode, date, "0000" AS time, 'A' AS type, -amount
FROM account) AS unsorted
ORDER BY ccode, date, time, type) AS sorted) AS numbered
The idea here is that you first need to get your booking (debits) and account (credits) lined up as in the "unsorted" statement above. Then, you need to sort them by date and time as in the "sorted" statement. Next, add row numbers to the results as in the "numbered" statement. Finally, select all that data along with a sum of amounts with row number less than or equal to the current row number that matches your ccode.
In the future, please consider using a transaction table of some sort which holds all account balance changes in a single table.
I have found the answer.
It is to use cummulative sql statement to find a running balance