query with name and time spent with max views - mysql

I am having data like this database table:
cookie_id cookie_name cookie_url cookie_view date time
1 S265nEmXMz /test.php 1 23/11/16 02:51:39
2 S265nEmXMz /test.php 2 23/11/16 02:52:45
3 5h2Rae6YRO /test.php 1 23/11/16 02:52:58
I want to get cookie_name having max number of views and substraction of max to min time like
cookie_id cookie_name cookie_url cookie_view date time
1 S265nEmXMz /test.php 2 23/11/16 00:01:06
2 5h2Rae6YRO /test.php 1 23/11/16 02:52:58

You should use subtime to get the time difference. The other detail is that you need CASE for when you only have one cookie to avoid getting 0 as time.
SELECT `cookie_id`,
`cookie_name`,
`cookie_url`,
MAX(`cookie_view`) cookie_views,
`date`,
( CASE
WHEN Count(`cookie_id`) > 1 THEN Subtime(Max(`time`), Min(`time`))
ELSE time
end ) time_in
FROM `cookies`
GROUP BY `cookie_name`
ORDER BY cookie_id

Try:
SELECT cookie_name,
cookie_url,
Max(cookie_view) AS maxview,
Subtime(Max(time), Min(time)) AS spent,
date
FROM `cookie_table`
GROUP BY cookie_name

Related

How to check how many time a car is parked on

I need a report of which cars (license plates) are parked in and when.
This is an example of my table.
id lic_plate datetime lane
_________________________________________________
10 1234-JM 2022-10-07 12:24:33 IN
11 1234-JM 2022-10-07 12:29:57 OUT
12 5678-PC 2022-10-07 15:14:17 IN
So when I query which are those who are parked more than - for instance - 1hour, the result Now (2022-10-07 15:14:17) should be "5678-PC".
I have tried:
SELECT lic_plate, COUNT(*) AS result
FROM table
GROUP BY lic_plate
HAVING COUNT(lane='IN') AND COUNT(lane='OUT')
But I can't figure out where I insert the HOUR query. And it seems to me that this kind of solution will have some "hidden" flaws.
What will be the best approach?
Thanks in advance.
select max(id) as id
,lic_plate
,max(datetime) as datetime
,timediff(now(),max(datetime)) as time_parked
from t
group by lic_plate
having count(*)%2 != 0
id
lic_plate
datetime
time_parked
12
5678-PC
2022-10-07 15:14:17
69:26:12
Fiddle
We check the time difference between the current date and time and datetime. We count how many records we have per car and if we have even numbers of records we filter the results as we know the car is out already.
select id
,lic_plate
,datetime
,time_parked
from (
select *
,count(*) over(partition by lic_plate) as chk
,timediff(now(),datetime) as time_parked
from t
) t
where chk%2 != 0
id
lic_plate
datetime
time_parked
12
5678-PC
2022-10-07 15:14:17
00:29:58
Fiddle

Count of past instances in an appended table

This is my desired output:
CampaignName CampaignDate UsersTargeted CountOfUsersBought
2x1 2018-11-24 1 (UserId 2) 1 (UserId 2)
3x2 2018-11-25 2 (Both) 1 (UserId 1)
'CountOfUsersBought' I want it to be Amongst All Targeted Users.
And the Table (Updated Daily) from where I get the data to fill the previous output has the following structure:
UserId EligibleForOffer(0,1) BoughtToday(0,1) Timestamp
1 0 0 2018-11-24
1 1 0 2018-11-25
1 1 1 2018-11-26
1 0 0 2018-11-27
2 1 0 2018-11-24
2 1 1 2018-11-25
2 1 0 2018-11-26
2 0 1 2018-11-27
I want to store on the variable 'CountOfUsersBought' the count of all the users that actually bought, not only today but all time. How would you go about doing this query?
Please note that users also buy without an offer, so I only want to count the past instances WHERE EligibleForOffer = 1 AND BoughtToday = 1 AND Timestamp <= 'CampaignDate'+ 1 day
I know for another table the users that are targeted for each campaign, I just want to keep for more than 'today' the count of users that took the offer that was given to them.
You can GROUP BY dates and use SUM the find how many users eligible for campaigns and use CASE to do your conditions. And bonus is MIN to find which specific user related with the condition is only one user match.
CREATE TABLE Campain
(
UserId INT
,EligibleForOffer BIT
,BoughtToday BIT
,Timestamp DATE
)
INSERT INTO Campain
VALUES
(1,0,0,'2018-11-24')
,(1,1,0,'2018-11-25')
,(1,1,1,'2018-11-26')
,(1,0,0,'2018-11-27')
,(2,1,0,'2018-11-24')
,(2,1,1,'2018-11-25')
,(2,1,0,'2018-11-26')
,(2,0,1,'2018-11-27')
SELECT Timestamp
,SUM(CAST(EligibleForOffer AS INT)) NumberOfUsersTargeted
,CASE WHEN SUM(CAST(EligibleForOffer AS INT))=1 THEN 'UserId-'+CAST(MIN(UserId) AS VARCHAR) WHEN SUM(CAST(EligibleForOffer AS INT))>1 THEN 'Multiple Users(Both)' ELSE 'No Target' END UsersTargetedDetail
,SUM(CAST(BoughtToday AS INT)) NumberOfBought
,CASE WHEN SUM(CAST(BoughtToday AS INT))=1 THEN 'UserId-'+CAST(MIN(UserId) AS VARCHAR) WHEN SUM(CAST(BoughtToday AS INT))>1 THEN 'Multiple Users(Both)' ELSE 'No Buying' END BoughtDetail
FROM Campain
GROUP BY Timestamp

MySQL query to get that row which has the last day of first month of date field

In my database I have a field named DateLastSaved:
Suppose the values are:
1. 2016-05-12 08:07:00,
2. 2016-05-22 09:06:00,
3. 2016-05-22 09:06:00,
4. 2016-06-13 09:00:00,
5. 2016-06-13 09:00:00
I wan't such query that would return me that row whose DateLastSaved field has the minimum month, in above case "5" and the maximum date of that month, which is 2, 3, but my query should return one result, i.e either 2 or 3.
I am using the following query:
SELECT MIN(LAST_DAY(DateLastSaved))FirstMonth
FROM InitialLog
WHERE FileName='Dr. Adam Kotowski Patient Names.doc'
But it is returning me the first date, that is, minimum, not the maximum one. Any suggestions?
Try this:
SELECT *
FROM InitialLog
WHERE MONTH(DateLastSaved) = (SELECT MIN(MONTH(DateLastSaved)) FROM InitialLog)
ORDER BY DAY(DateLastSaved) DESC LIMIT 1
Demo here

Checking consecutive values at a MySQL query

I have a MySQL table like this:
ID - Time - Value
And I'm getting every pair of ID, Time (grouped by ID) where Value is greater than a certain threshold. So basicaly, I'm getting every ID which has at least one time a value greater than the threshold. The query looks like this:
SELECT ID, Time FROM mydb.MYTABLE
WHERE Value>%s AND Time>=%s AND Time<=%s
GROUP BY ID
EDIT: The Time checks allow to operate in a time range of my choice between all the data which is into the table; it has nothing else to do with what I am asking.
It works perfectly, but now I want to add some filtering: I want it to avoid those times the value is greater than the threshold (let's call it alarms) if the alarm hasn't happened also the Time just before or just after. I mean: if the alarm accurs at a single, isolated instant of time instead of two consecutive instants of time, I'll consider it is a false alarm and avoid it to be returned at the query response.
Of course I can do this with a call for each Id to check for this, but I'd like to do this in a single query to make it faster. I guess I could use conditionals, but I don't have that expertise at MySQL.
Any help?
EDIT2: Example for Threshold = 10
ID - Time - Value
1 - 2004 - 9
1 - 2005 - 11
1 - 2006 - 8
2 - 2107 - 12
2 - 2109 - 13
3 - 3402 - 11
3 - 3403 - 12
In this example, only ID 3 should be a valid alarm, since 2 consecutive time values for this ID have their value > threshold. ID 1 has a single, isolated alarm, so it should be filteres. For ID 2 there are 2 alarms, but not consecutive, so it should be also filtered.
Something like this:
10 - is a threshold
0 - minimum of the time period
100000 - maximum of the time period
select ID, min(Time)
from
(
SELECT ID, Time,
(select max(time) from t
where Time<t1.Time
and Id=t1.Id
and Value>10) LAG_G,
(select max(time) from t
where Time<t1.Time
and Id=t1.Id
and Value<=10) LAG_L,
(select min(time) from t
where Time>t1.Time
and Id=t1.Id
and Value>10) LEAD_G,
(select min(time) from t
where Time>t1.Time
and Id=t1.Id
and Value<=10) LEAD_L
FROM t as t1
WHERE Value>10 AND Time>=0 AND Time<=100000
) t3
where ifnull(LAG_G,0)>ifnull(LAG_L,0)
OR
ifnull(LEAD_G,100000)<ifnull(LEAD_L,100000)
GROUP BY ID
SQLFiddle demo
This query works for searching near records.
If you need to search records by Time (+1, -1 ) as you've mentioned in the comment try this query:
select ID, min(Time) from t as t1
where Value>10
AND Time>=%s2 AND Time<=%s1
and
(
Exists(select 1 from t where Value>10
and Id=t1.Id
and Time=t1.Time-1)
OR
Exists(select 1 from t where Value>10
and Id=t1.Id
and Time=t1.Time+1)
)
group by ID
SQLFiddle demo
such alarm ?
SELECT ID, Time , count(if(value>%treshold ,1,0)) alert_active
FROM mydb.MYTABLE
WHERE Value>%s3 AND Time>=%s2 AND Time<=%s1
GROUP BY ID;
i don't understand exactly:
In this example, only ID 3 should be a valid alarm, since 2
consecutive time values for this ID have their value > threshold. ID 1
has a single, isolated alarm, so it should be filteres. For ID 2 there
are 2 alarms, but not consecutive, so it should be also filtered.
I guess that You want filter alerts:
SELECT ID, Time
FROM mydb.MYTABLE
WHERE Value>%s3 AND Time>=%s2 AND Time<=%s1
GROUP BY ID
having value<%treshold;

Given a date find the previous &/or current and next x# Dates in MySQL non-linear

I have a table code_prices that looks something like this:
CODE | DATE | PRICE
ABC | 25-7-2011 | 2.81
ABC | 23-7-2011 | 2.52
ABC | 22-7-2011 | 2.53
ABC | 21-7-2011 | 2.54
ABC | 20-7-2011 | 2.58
ABC | 17-7-2011 | 2.42
ABC | 16-7-2011 | 2.38
The problem with the data set is there are gaps in the dates, so I may want to look for the price of item ABC on the 18th however there is no entry because the item wasnt sold on this date. So I would like to return the most recent hisotrical entry for the price.
Say if I query on the date 19-7-2011, I would like to return the entry on the 17th then the next 10 avalaible entries.
If however I query for the price of ABC on the 20th, I would want to return the price on the 20th and the next 10 prices after that...
What is the most efficient way to go about this either in SQL statement or using a stored proc.
I can think of just writing a stored proc which takes the date as a param and then querying for all rows where DATE >= QUERY-DATE ordering by the date and then selecting the 11 items (via limit). Then basically I need to see if that set contains the current date, if it does then return, otherwise I will need to return the 10 most recent entires out of those 11 and also do another query on the table to return the previous entry by getting the max date where date < QUERY-DATE. I am thinking there might be a better way, however I'm not an expert with SQL (clearly)...
Thanks!
This is for one specific code:
SELECT code, `date`, price
FROM code_prices
WHERE code = #inputCode
AND `date` >=
( SELECT MAX(`date`)
FROM code_prices
WHERE code = #inputCode
AND `date` <= #inputDate
)
ORDER BY `date`
LIMIT 11
For ABC and 19-7-2011, the above will you give the row for 17-7-2011 and the 10 subsequent rows (20-7-2011, 21-7-2011, etc)
I'm not entirely clear on what you want to achieve, but I'll have a go anyway. This searches for the ID of the row that contains a date less than or equal to your specified date. It then uses that ID to return all rows with an ID greater than or equal to that value. It assumes that you have a column other than the date column on which the rows can be ordered. This is because you said that the dates are non-linear - I assume that you must have some other way of ordering the rows.
SELECT id, code, dt, price
FROM code_prices
WHERE id >= (
SELECT id
FROM code_prices
WHERE dt <= '2011-07-24'
ORDER BY dt DESC
LIMIT 1 )
ORDER BY id
LIMIT 11;
Alternative with code condition - thanks to #ypercube for highlighting that ;-)
SELECT id, code, dt, price
FROM code_prices
WHERE code = 'ABC'
AND id >= (
SELECT id
FROM code_prices
WHERE dt <= '2011-07-23'
AND code = 'ABC'
ORDER BY dt DESC
LIMIT 1 )
ORDER BY id
LIMIT 11;