SQL Query AVG Date Time In same Table Column - sql

I’m trying to make a query that returns the difference of days to get the average of days in a period of time. This is the situation I need to get the max date from the status 2 and the max date from the status 3 from a request and get how much time the user spend on that period of time
So far this is the query I Have right now I get the mas and min and the difference between the days but are not the max of the status 2 and the max of status 3
Query I have so far:
SELECT distinct t1.user, t1.Request,
Min(t1.Time) as MinDate,
Max(t1.Time) as MaxDate,
DATEDIFF(day, MIN(t1.Time), MAX(t1.Time))
FROM [Hst_Log] t1
where t1.Request = 146800
GROUP BY t1.Request, t1.user
ORDER BY t1.user, max(t1.Time) desc
Example table:
-------------------------------
user | Request | Status | Time
-------------------------------
User 1 | 2 | 1 | 6/1/15 3:25 PM
User 2 | 1 | 1 | 2/1/15 3:24 PM
User 2 | 3 | 1 | 2/1/15 3:24 PM
User 1 | 4 | 1 | 5/10/15 3:18 PM
User 3 | 3 | 2 | 5/4/15 2:36 PM
User 2 | 2 | 2 | 6/4/15 2:34 PM
User 3 | 2 | 3 | 6/10/15 5:51 PM
User 1 | 1 | 2 | 5/1/15 5:49 PM
User 3 | 4 | 2 | 5/16/15 2:39 PM
User 2 | 4 | 2 | 5/17/15 2:32 PM
User 2 | 3 | 2 | 4/6/15 2:22 PM
User 2 | 3 | 3 | 4/7/15 2:06 PM
-------------------------------
I will appreciate all the help

You'll need to use subqueries since the groups for the min and max times are different. One query will pull the min value where the status is 2. Another will pull the max value where the status is 3.
Something like this:
SELECT MinDt.[User], minDt.MinTime, MaxDt.MaxTime, datediff(d,minDt.MinTime, MaxDt.MaxTime) as TimeSpan
FROM
(SELECT t1.[user], t1.Request,
Min(t1.Time) as MinTime
FROM [Hst_Log] t1
where t1.Request = 146800
and t1.[status] = 2
GROUP BY t1.Request, t1.[user]) MinDt
INNER JOIN
(SELECT t1.[user], t1.Request,
Max(t1.Time) as MaxTime
FROM [Hst_Log] t1
where t1.[status] = 3
GROUP BY t1.Request, t1.[user]) MaxDt
ON MinDt.[User] = MaxDt.[User] and minDt.Request = maxDt.Request

something like this?
(mysql)
SELECT t.*,MAX(t.UFecha), x.*,y.*,Min(t.UFecha) as MinDate,
Max(t.UFecha) as MaxDate,
avg(x.Expr2+y.Expr3),//?????
DATEDIFF(MIN(t.UFecha), MAX(t.UFecha)) AS Expr1
FROM `app_upgrade_hst_log` t
left join(select count(*),Request, DATEDIFF(MIN(UFecha), MAX(UFecha)) AS Expr2 FROM `app_upgrade_hst_log` where Status=1 group by Request,Status) x on t.Request= x.Request
left join(select count(*),Request, DATEDIFF(MIN(UFecha), MAX(UFecha)) AS Expr3 FROM `app_upgrade_hst_log` where Status=2) y on t.Request= y.Request
group by t.Request,t.Status

What is the SQL-Server version? Maybe you could use your query as CTE and do a follow-up SELECT where you can use the Min and Max date as date period.
EDIT: Exampel
WITH myCTE AS
(
put your query here
)
SELECT * FROM myCTE
You can use myCTE for further joins too, pick out the needed date, use sub-select, what ever... AND: have a look on the OVER-link, could be helpfull...
Depending on the version you could also think about using OVER
https://msdn.microsoft.com/en-us/library/ms189461.aspx

Related

SQL: Selecting data from multiple tables with multiple records to select and join

I have three tables: VolunteerRelationships, Organizations, and CampaignDates. I'm trying to write a query that will give me the organization id and name, and the org's start and end campaign dates for the current campaign year <#CampaignYear>, based on the selected volunteer <#SelectedInd>.
Dates are stored as separate column values for day, month and year which I'm trying to cast into a more an formatted date value. If I can get this, I'd also like to use a case statement to get the status of the campaign based on whether the date campaign dates are upcoming, currently running, or already closed, but need to get the first part of the query first.
Sorry if I'm leaving a lot of needed info out, this is my first time posting a question to this forumn. Thank you!
VolunteerRelationships
id | name | managesId |expiryDate
1 | john | 1 |
2 | jack | 2 |6/30/2020
3 | jerry| 3 |12/31/2021
Organizations
id | name1
1 | ACME
CampaignDates
orgId | dateDay | dateMonth | dateYear | dateType | Campaign Year
1 | 5 | 11 | 2020 | Start | 2020
1 | 15 | 11 | 2020 | End | 2020
Result
orgId | orgName | startDate | endDate | Status
1 | ACME | 2020-01-01| 2020-01-15 | Closed
select
v.MANAGEDACCOUNT,
o.Name1,
select * from
(select cast(cast dateyear*1000 + datemonth*100 + dateday as varchar(255)) as date as date1 from <#Schema>.CampaignDates where datetype = 'Start' and campaignyear = <#CampaignYear> and orgaccountnumber = v.MANAGEDACCOUNT) d1,
(select cast(cast dateyear*1000 + datemonth*100 + dateday as varchar(255)) as date as date2 from <#Schema>.CampaignDates where datetype = 'End' and campaignyear = <#CampaignYear> and orgaccountnumber = v.MANAGEDACCOUNT) d2
from <#Schema>.VolunteerRelationships v
inner join <#Schema>.organizations o
on o.accountnumber=v.MANAGEDACCOUNT
where v.VOLUNTEERACCOUNT = <#SelectedInd> and ( v.EXPIRYDATE IS NULL OR v.EXPIRYDATE > <#Today> )

Count first occurrences in time (SQL)

I have a table like this
+----+---------------------+
| Id | Date application |
+----+---------------------+
| 1 | 2016-08-22 03:05:06 |
| 2 | 2016-08-22 03:05:06 |
| 1 | 2016-08-23 03:05:06 |
| 2 | 2016-08-23 03:05:06 |
+----+---------------------+
I would like to find out when was the first application for each user (ID)
and then to count how many occurred in the past 7 days
so far here is what I have
SELECT id,
min(date_of_application)
FROM mytable
GROUP BY id
ORDER BY date_of_application ASC
Will the min() work on dates ?
From there, how do I count how many first applications there are in the past 7 days ?
Please tag your database. min() will work on dates.
Assuming your is mysql db here is what you can do to get the application usage count in the past 7 days from now.
select
id, count(*) as 'appUsageCount'
from
mytable
where
dateApplication >= DATE(DATE_SUB(NOW(),INTERVAL 7 DAY))
and date_of_application <= DATE(NOW()))
group by id
#Neeraj: Using your query with little modification.
Try this:
select
id, count(id) as 'appUsageCount', min(date_of_application)
from
mytable
where
date_of_application >= DATE(DATE_SUB(NOW(),INTERVAL 7 DAY))
and date_of_application <= DATE(NOW()))
group by id

Select last record from data table for each device in devices table [duplicate]

This question already has answers here:
Select first row in each GROUP BY group?
(20 answers)
Closed 6 years ago.
I have a problem with the executing speed of my sql query to postgres database.
I have 2 tables:
table 1: DEVICES
ID | NAME
------------------
1 | first device
2 | second device
table 2: DATA
ID | DEVICE_ID | TIME | DATA
--------------------------------------------
1 | 1 | 2016-07-14 2:00:00 | data1
2 | 1 | 2016-07-14 1:00:00 | data2
3 | 2 | 2016-07-14 4:00:00 | data3
4 | 1 | 2016-07-14 3:00:00 | data4
5 | 2 | 2016-07-14 6:00:00 | data5
6 | 2 | 2016-07-14 5:00:00 | data6
I need get this select's result table:
ID | DEVICE_ID | TIME | DATA
-------------------------------------------
4 | 1 | 2016-07-14 3:00:00 | data4
5 | 2 | 2016-07-14 6:00:00 | data5
i.e. for each device in devices table I need to get only one data record with the last TIME value.
This is my sql query:
SELECT * FROM db.data d
WHERE d.time = (
SELECT MAX(d2.time) FROM db.data d2
WHERE d2.device_id = d.device_id);
This is HQL query equivalent:
SELECT d FROM Data d
WHERE d.time = (
SELECT MAX(d2.time) FROM Data d2
WHERE d2.device.id = t2.device.id)
Yes, I use Hibernate ORM in my project - may this info will be useful for someone.
I got correct answer on my queries, BUT it's too long - about 5-10 seconds on 10k records in data table and only 2 devices in devices table. It's terrible.
First of all, I thought that problem is in Hibernate. But native sql query from psql in linux terminal execute the same time as through hibernate.
How can I optimize my query? This query is too complexity:
O(device_count * data_count^2)
Since you're using Postgres, you could use window functions to achieve this, like so:
select
sq.id,
sq.device_id,
sq.time,
sq.data
from (
select
data.*,
row_number() over (partition by data.device_id order by data.time desc) as rnk
from
data
) sq
where
sq.rnk = 1
The row_number() window function first ranks the rows in the data table on the basis of the device_id and time columns, and the outer query then picks the highest-ranked rows.

SQL Query Compare values in per 15 minutes and display the result per hour

I have a table with 2 columns. UTCTime and Values.
The UTCTime is in 15 mins increment. I want a query that would compare the value to the previous value in one hour span and display a value between 0 and 4 depends on if the values are constant. In other words there is an entry for every 15 minute increment and the value can be constant so I just need to check each value to the previous one per hour.
For example
+---------|-------+
| UTCTime | Value |
------------------|
| 12:00 | 18.2 |
| 12:15 | 87.3 |
| 12:30 | 55.91 |
| 12:45 | 55.91 |
| 1:00 | 37.3 |
| 1:15 | 47.3 |
| 1:30 | 47.3 |
| 1:45 | 47.3 |
| 2:00 | 37.3 |
+---------|-------+
In this case, I just want a Query that would compare the 12:45 value to the 12:30 and 12:30 to 12:15 and so on. Since we are comparing in only one hour span then the constant values must be between 0 and 4 (O there is no constant values, 1 there is one like in the example above)
The query should display:
+----------+----------------+
| UTCTime | ConstantValues |
----------------------------|
| 12:00 | 1 |
| 1:00 | 2 |
+----------|----------------+
I just wanted to mention that I am new to SQL programming.
Thank you.
See SQL fiddle here
Below is the query you need and a working solution Note: I changed the timeframe to 24 hrs
;with SourceData(HourTime, Value, RowNum)
as
(
select
datepart(hh, UTCTime) HourTime,
Value,
row_number() over (partition by datepart(hh, UTCTime) order by UTCTime) RowNum
from foo
union
select
datepart(hh, UTCTime) - 1 HourTime,
Value,
5
from foo
where datepart(mi, UTCTime) = 0
)
select cast(A.HourTime as varchar) + ':00' UTCTime, sum(case when A.Value = B.Value then 1 else 0 end) ConstantValues
from SourceData A
inner join SourceData B on A.HourTime = B.HourTime and
(B.RowNum = (A.RowNum - 1))
group by cast(A.HourTime as varchar) + ':00'
select SUBSTRING_INDEX(UTCTime,':',1) as time,value, count(*)-1 as total
from foo group by value,time having total >= 1;
fiddle
Mine isn't much different from Vasanth's, same idea different approach.
The idea is that you need recursion to carry it out simply. You could also use the LEAD() function to look at rows ahead of your current row, but in this case that would require a big case statement to cover every outcome.
;WITH T
AS (
SELECT a.UTCTime,b.VALUE,ROW_NUMBER() OVER(PARTITION BY a.UTCTime ORDER BY b.UTCTime DESC)'RowRank'
FROM (SELECT *
FROM #Table1
WHERE DATEPART(MINUTE,UTCTime) = 0
)a
JOIN #Table1 b
ON b.UTCTIME BETWEEN a.UTCTIME AND DATEADD(hour,1,a.UTCTIME)
)
SELECT T.UTCTime, SUM(CASE WHEN T.Value = T2.Value THEN 1 ELSE 0 END)
FROM T
JOIN T T2
ON T.UTCTime = T2.UTCTime
AND T.RowRank = T2.RowRank -1
GROUP BY T.UTCTime
If you run the portion inside the ;WITH T AS ( ) you'll see that gets us the hour we're looking at and the values in order by time. That is used in the recursive portion below by joining to itself and evaluating each row compared to the next row (hence the RowRank - 1) on the JOIN.

SQL: How to get AVG on each day with a single query

I would like to get the average value of each day. For example, I would like to get 4 instead of getting 3 and 5 on "20130511". How can I do that on a single query? (Not hard code)
Select Val from Table 1 where??????????
Table1 :
Date Val
----------------
20130511 | 3
20130511 | 5
20130512 | 5
20130512 | 1
20130512 | 2
20130512 | 6
20130512 | 2
20130513 | 2
You have to group the date
SELECT Date, AVG(Val) FROM TABLE GROUP BY Date
You can group by date and do it in a single pass
SELECT DATE, SUM(VALUE)/COUNT(*) AS AVERAGE
FROM TABLE
GROUP BY DATE