MySQL AVG of TIMESTAMPDIFF function with WHERE CLAUSE - mysql

I have a table from which I am trying to get the average duration. I am using the following code
/*TIME DURATION*/
SELECT DATE(createDate),
AVG(TIMESTAMPDIFF(SECOND, min(createDate), max(createDate))) AS Duration
FROM Impressions
WHERE session_id IN (
SELECT session_id
FROM carts
WHERE createDate >= '2014-06-30'AND createDate < '2014-07-07'
AND HOUR(createDate) >= 10
AND HOUR(createDate) < 21
)
AND session_Id <> ''
GROUP BY DATE(createDate);
However, I am getting the following error and cannot understand why. Any help will be appreciated.
ErrorCode: -2147467259, Number: 1111
ErrorMessage: Invalid use of group function

I would recommend you to use the query like this:
SELECT DATE(tbl.createDate),
AVG(TIMESTAMPDIFF(SECOND, tbl.minDt, tbl.maxDt)) AS Duration
FROM (SELECT DATE(i.createDate) as createDate,
min(i.createDate) minDt,
max(i.createDate) maxDt
FROM Impressions i INNER JOIN
carts c ON (i.session_id = c.session_id)
WHERE c.createDate >= '2014-06-30'
AND c.createDate < '2014-07-07'
AND HOUR(c.createDate) >= 10
AND HOUR(c.createDate) < 21
AND i.session_Id <> ''
GROUP BY DATE(i.createDate) ) as tbl
GROUP BY DATE(tbl.createDate);

Related

(MySQL 5.7) How to combine my two queries?

How can I combine my two queries in MySQL 5.7:
(windows functions doesn't work)
1: This query is finding all dialogues where more than 10 messages and spaced at least an hour apart.
SELECT `dialog_id`
FROM `messages`
GROUP BY `dialog_id`
HAVING COUNT(*) >= 10
AND MIN(`timestamp`) + INTERVAL 1 HOUR < MAX(`timestamp`)
2: The second query selects two last rows for each dialogue.
SELECT * FROM messages tbl WHERE
(SELECT COUNT(*) FROM messages tbl1 WHERE tbl1.dialog_id = tbl.dialog_id AND tbl1.id >= tbl.id AND
(user_from = :user_from OR user_to = :user_to)) <= 2 ORDER BY dialog_id DESC
So, what I want is to select last two rows for each dialogue that lasted more than an hour and where more than 10 messages were sent.
Though I didn't got you properly is this what you are looking for:
SELECT * FROM messages tbl WHERE
(SELECT COUNT(*) FROM messages tbl1 WHERE tbl1.dialog_id = tbl.dialog_id AND tbl1.id >= tbl.id AND
(user_from = :user_from OR user_to = :user_to)) <= 2
and dialog_id in (SELECT `dialog_id`
FROM `messages`
GROUP BY `dialog_id`
HAVING COUNT(*) >= 10
AND MIN(`timestamp`) + INTERVAL 1 HOUR < MAX(`timestamp`))
ORDER BY dialog_id DESC
One way you can accomplish this with a subquery:
SELECT *
FROM messages tbl
WHERE (
SELECT COUNT(*)
messages tbl1
tbl1.dialog_id = tbl.dialog_id
tbl1.id >= tbl.id
(user_from = :user_from OR user_to = :user_to)) <= 2
and dialog_id in (
SELECT `dialog_id`
FROM `messages`
GROUP BY `dialog_id`
HAVING COUNT(*) >= 10
AND MIN(`timestamp`) + INTERVAL 1 HOUR < MAX(`timestamp`))
ORDER BY dialog_id DESC
You might have to adjust it slightly, since I don't have the full structure of your tables, but the principle would go as follows: get all the dialogue_ids matching your 10 and over an hour criteria, then use it to limit the messages returned from your "Get the most recent two" logic.

How to change format of the MySQL result?

I have a complex mysql query language, including several sub queries and my final result is as below. There is something that I am dealing with it and I can't solve it and this is a way result is being presented. I am wondering to know how can i change the structure of the result in a way that the result is being presented only in one row and I don't want to see NULL fields. I mean something like below
This is mysql query
select count(*) as userRetentionSameDay, null as 'userRetentionDiffDay' from (SELECT date(`timestamp`), `user_xmpp_login`
FROM table1
WHERE DATE(`timestamp` ) = CURDATE() - INTERVAL 1 DAY) as res1
right join (select date(ts), user
from table2
WHERE DATE(ts ) = CURDATE() - INTERVAL 1 DAY
and product_id REGEXP ("^(europe+$" )) as lej1
on lej1.user = res1.`user_xmpp_login`
where res1.`user_xmpp_login` IS not NULL
union all
select null as 'userRetentionSameDay', count(*) as userRetentionDiffDay from (SELECT date(`timestamp`), `user_xmpp_login`
FROM table1
WHERE DATE(`timestamp` ) = CURDATE() - INTERVAL 1 DAY) as res1
right join (select date(ts), user
from table2
WHERE DATE(ts ) = CURDATE() - INTERVAL 1 DAY
and product_id REGEXP ("^(europe+$" )) as lej2
on lej2.user = res1.`user_xmpp_login`
where res1.`user_xmpp_login` IS NULL;
What are the recommended solutions to doing that?
try this.
SELECT A.userRetentionSameDay,B.userRetentionDiffDay FROM (
SELECT COUNT() AS userRetentionSameDay FROM
(
SELECT DATE(timestamp), user_xmpp_login
FROM table1
WHERE DATE(timestamp ) = CURDATE() - INTERVAL 1 DAY) AS res1
RIGHT JOIN (SELECT DATE(ts), USER
FROM table2
WHERE DATE(ts ) = CURDATE() - INTERVAL 1 DAY
AND product_id REGEXP ("^(europe+$" )) AS lej1
ON lej1.user = res1.user_xmpp_login
WHERE res1.user_xmpp_login IS NOT NULL
) A,
(
SELECT COUNT() AS userRetentionDiffDay FROM (
SELECT DATE(timestamp), user_xmpp_login
FROM table1
WHERE DATE(timestamp ) = CURDATE() - INTERVAL 1 DAY
) AS res1
RIGHT JOIN (SELECT DATE(ts), USER
FROM table2
WHERE DATE(ts ) = CURDATE() - INTERVAL 1 DAY
AND product_id REGEXP ("^(europe+$" )
) AS lej2
ON lej2.user = res1.user_xmpp_login
WHERE res1.user_xmpp_login IS NULL
) B;

how to find duplicate records in a table within a predefined time period in sql

For example, i have following table
Mobile number Timestamp
123456 17-09-2015 11:30
455677 17-09-2015 12:15
123456 17-09-2015 12:25
453377 17-09-2015 13:15
If now is 11:30, I want to scan my table and find rows with the same numbers within the past 1 hour.
That's my SQL statement:
select a.number, a.time
from mytable a inner join
(select number, time
from mytable b
where time>=now()-Interval 1 hour and time<=now ()
group by number
Having count(*) > 1
) b
on a.number = b.number and a.time = b.time
I want to find duplicate rown with the same numbers happening within 1 hour. I should output the number and timestamp.
How about just using exists?
select t.*
from mytable t
where t.time >= now() - Interval 1 hour and
t.time <= now() and
exists (select 1
from mytable t2
where t2.number = t.number and
t2.time >= now() - Interval 1 hour and
t2.time <= now () and
t2.time <> t.time
);
However, I suspect that the problem with your query is the join to time. Just remove the time from the subquery and the on clause and you will get all numbers. Alternatively, use group by:
select t.number, group_concat(time)
from mytable t
where t.time >= now() - Interval 1 hour and
t.time <= now()
group by t.number
having count(*) > 1;

Refine a SQL query for getting count(*)

I have the following query that gets some results I would like to group by attribute 'state'.
I tried different subquery but they didn't work and I'm a bit blocked.
The SQL is:
SELECT state, id_candidate_basic, MAX( DATE ) FROM `candidate_state`
WHERE `date` <= '2013-09-06 00:00:00' GROUP BY id_candidate_basic
ORDER BY `candidate_state`.`id_candidate_basic` DESC
This returns currently:
I would get a count(*) for each state. Example:
F, 14
I, 10
O, 9
SELECT state,
id_candidate_basic,
MAX( DATE ),
COALESCE(totalCount, 0) totalCount
FROM `candidate_state`
LEFT JOIN
(
SELECT state, COUNT(*) totalCount
FROM candidate_state
WHERE `date` <= '2013-09-06 00:00:00'
GROUP BY state
) ON candidate_state.state = b.state
WHERE `date` <= '2013-09-06 00:00:00'
GROUP BY id_candidate_basic
ORDER BY `candidate_state`.`id_candidate_basic` DESC

MYSQL loop this code

I want the following code to run with multiple end dates. those end dates must al be the first day of the month.
I can execute the code several times while changing the end date myself but thats to much work of i want montly data from 2001 until now. So my guess is I have to loop this?
Here is the code i'm using:
Select t4.Count, t4.Status
From(
SELECT count(l.VoerID) as Count, l.Datum, l.Status, l.LogID
FROM (
SELECT k.VoerID, k.Datum, MAX(k.LogID) AS LogID
FROM DB.LogStatus k
Where Datum > '2001-01-01'
and Datum < '2013-07-01'
GROUP BY k.VoerID
) m
JOIN DB.LogStatus l
ON l.VoerID = m.VoertuigID AND l.LogID = m.LogID
Where status in ('x',y,'z')
Group by Status
)t4
Who can help?
EDIT::::: #STEPH
When I use this peace of code (1):
SELECT VoertID,max(LogID) as MaxLogID,Datum
from DB.LogStatus
WHERE Datum >= '2001-01-01'
and Datum < '2013-07-01'
and VoerID = '50789'
GROUP BY VoerID
i get VoerID 50789 with the last LogID but not the corresponding date. hows that possible?
Based on your output, you need to manipulate your date to always return the first of the month.
In the SQL below, I have presented a moethod to do so that involves working out how many days past the begining of the month (relative to each date) there has been and substracting it.
SELECT date_sub(Datum,interval day(Datum)-1 day) datum, status, count(l.VoerID) as count
FROM DB.LogStatus l
INNER JOIN (SELECT VoerID,max(LogID) as MaxLogID
from DB.LogStatus
WHERE Datum >= '2001-01-01'
and Datum < '2013-07-01'
GROUP BY VoerID) maxl on l.VoerID=Maxl.VoerID and l.LogID=Maxl.MaxLogID
Where status in ('x','y','z')
and Datum >= '2001-01-01'
and Datum < '2013-07-01'
GROUP BY date_sub(Datum,interval day(Datum)-1 day),status
Breaking down your original code:
Return for a given VoerID, return the FIRST Date and MAX LogID
SELECT k.VoerID, k.Datum, MAX(k.LogID) AS LogID
FROM DB.LogStatus k
Where Datum > '2001-01-01'
and Datum < '2013-07-01'
GROUP BY k.VoerID
Get all items from the log where the status is in a range and where the LogIDs match and the VoerID in the table matches the VoertuigID from the derived table (not actually present in code). Group by log status and get FIRST Datum, FIRST LogID and the COUNT
SELECT count(l.VoerID) as Count, l.Datum, l.Status, l.LogID
FROM ( step1 ) m
JOIN DB.LogStatus l
ON l.VoerID = m.VoertuigID AND l.LogID = m.LogID
Where status in ('x',y,'z')
Group by Status
Return Count and Status columns from 2
The revised code does:
Identifies last LogID for each VoerID within certain dates
SELECT VoerID,max(LogID) as MaxLogID
from DB.LogStatus
WHERE Datum >= '2001-01-01'
and Datum < '2013-07-01'
GROUP BY VoerID
Restricts log by these max LogIDs, then filters on relevant statuses, and then counts the number of rows per status per first of month
SELECT date_sub(Datum,interval day(Datum)-1 day) datum, status, count(l.VoerID) as count
FROM DB.LogStatus l
INNER JOIN ( m ) maxl on l.VoerID=Maxl.VoerID and l.LogID=Maxl.MaxLogID
Where status in ('x','y','z')
and Datum >= '2001-01-01'
and Datum < '2013-07-01'
GROUP BY date_sub(Datum,interval day(Datum)-1 day),status