INSERT only if SELECT returns no rows - mysql

I'm tracking a users visit to a website by recording them in a database. A visit has a cooldown period of 6 hours. For this reason, I want to add a row to the table visits only if a user last visited the current website over 6 hours ago. If the last visit was less than 6 hours ago, do nothing.
I've looked around for answers to this and found plenty of quite similar issues, but none of those worked for me.
This is last query I tried:
INSERT INTO visits (user_id, web_id)
SELECT (66, 2) FROM websites WHERE NOT EXISTS (
SELECT 1 FROM visits WHERE web_id = 2 and user_id = 66 and added_on >= NOW() - INTERVAL 6 HOUR
)
I'm getting a syntax error near WHERE NOT EXISTS.

You might want to enforce this rule with a trigger rather than in the application. But I think the problem are the parentheses in the SELECT clause:
INSERT INTO visits (user_id, web_id)
SELECT 66, 2
FROM websites
WHERE NOT EXISTS (SELECT 1
FROM visits
WHERE web_id = 2 and user_id = 66 and
added_on >= NOW() - INTERVAL 6 HOUR
);
Hmmm . . . Your query is strange. What is websites? Your query is going to insert one row for every row in that table. It seems unlikely that you want this behavior. Perhaps you just want this:
INSERT INTO visits (user_id, web_id)
SELECT w.user_id, w.web_id
FROM (SELECT 66 as user_id, 2 as web_id) w
WHERE NOT EXISTS (SELECT 1
FROM visits v
WHERE v.web_id = w.web_id and
v.user_id = w.user_id and
v.added_on >= NOW() - INTERVAL 6 HOUR
);

you might try this ...
INSERT visits (user_id, web_id)
SELECT distinct user_id, web_id
FROM websites t join websites b
on b.user_id = t.user_id
and b.web_id = t.web_id
and b.added_on = (Select Max(added_on) From websites
Where id = t.user_id
and web_id = t.web_id
and added_on < t.added_on)
WHERE t.added_on >= NOW() - INTERVAL 6 HOUR
and user_id = 66
and web_id = 2
try the Select part by itself first, to see if it returns the correct result.
by the way, if you only have the userId and the webId in the visits table, without the datetime of the visit, how do you interpret the data when there are multiple rows for the same user/website combination, which are the result of visits more than six hours apart?

Related

MySQL insert only if a record's timestamp is past 5 minutes

What I am trying to accomplish in my query is:
Users can store their mobile number in my database, and if the same mobile number is inserted, it will check if 5 minutes had been passed, if it has it will store another record of the same number, if it hasn't then it will not store the record. The column in my database are: Name, contact and date(timestamp)
What I had played around with and written:
INSERT INTO users (name, contact) SELECT * FROM (SELECT 'test', '123') AS 1 WHERE NOT EXISTS ( SELECT time FROM users WHERE time <= now() + INTERVAL 5 MINUTE ) LIMIT 1
This will always fail to save the record into the database, since the time is always <= 5 minutes as I'm not matching it to any specific rows. So my question here is: How can I go about matching the 5 minutes interval to a specific mobile number? IE: I want to check if the mobile number '123' had already been in my database for past 5 minutes, if it has then you can use '123' again in the mobile number field.
Consider the following... I used 1 minute because it's quicker to test
drop table if exists my_table;
create table my_table
( id serial primary key
, number varchar(12) not null
, dt datetime not null
);
insert into my_table
select null
, '1111'
, now()
from (select 1)x
left
join my_table y
on y.number = '1111'
and y.dt >= now() - interval 1 minute
where y.id is null
limit 1;

Check multiple tables in one single query

I want to SELECT data from my MySQL using PHP but the WHERE clause can be kind of confusing.
Basically i want to select the appointments that are coming up, then checking if the business is wanting to send out reminders, then checking if the user wants to receive reminders. But I want to do all that in one query.
Here are my tables:
appointments
- appointment_date
- appointment_time
- business_id
- user_id
businesses
- reminders_enabled
users
- reminders_enabled
Here are the steps of what I want to do before I select the right data:
SELECT * FROM appointments WHERE DATE(appointment_date) = CURDATE() AND appointment_time is within the next 1 hour
From the data selected above from step #1, I want to filter it. I want to SELECT * FROM businesses WHERE business_id = business_id_from_step_1 AND reminders_enabled = 1
Then I want to filter it even more. If results are found after step 2, do another select: SELECT * FROM users WHERE user_id = user_id_from_step_1 AND reminders_enabled = 1
That's it after that. How can I do that? Thanks!
Something like this should work. The JOINs do the filtering as you describe in your steps 1-3:
SELECT *
FROM appointments a
JOIN businesses b ON b.business_id = a.business_id AND b.reminders_enabled = 1
JOIN users u ON u.user_id = a.user_id AND u.reminders_enabled = 1
WHERE DATE(a.appointment_date) = CURDATE() AND
a.appointment_time BETWEEN NOW() AND NOW() + INTERVAL 1 HOUR
SELECT * FROM appointments
WHERE DATE(appointment_date) = CURDATE()
AND appointment_time BETWEEN NOW() AND NOW() + INTERVAL 1 HOUR
AND business_id in (SELECT business_id FROM businesses WHERE reminders_enabled=1)
AND user_id in (SELECT user_id FROM users WHERE reminders_enabled=1)

insert visits after 5 minutes only

I'd like to insert visits like this:
id - user - visit - data
1 - 1 - 2 - date
2 - 1 - 3 - date
3 - 1 - 2 - date after 5 minutes from the first (id 1) - only insert if it has pasted more than 5 minutes from the last similar record.
user 1 visited user 2 and 3.
The problem is, I'd like to insert visits without repeating them in the first 5 minutes. After this I'd like to insert.
I tried:
INSERT INTO visits (user, visit, data)
SELECT '1', '2', NOW() WHERE NOT EXISTS (SELECT 1 FROM visits WHERE user = '1' AND visit = '2' AND data >= DATE_SUB(NOW(), INTERVAL 5 MINUTE))
but it is not working. any ideas?
You can express the logic in the insert:
INSERT INTO visits (user, visit, data)
SELECT u.user, u.visit, u.data
FROM (SELECT 1 as user, 2 as visit, NOW() as data) u
WHERE NOT EXISTS (SELECT 1
FROM visits v
WHERE v.user = u.user AND v.visit = u.visit AND
u.data >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)
);
This solves the problem for the particular INSERT. And that might be good enough. However, you are relying on the application to ensure data integrity. A trigger would ensure that no inserts or updates take place that violate your rule.

Count unique users from statistics table based on hourly groupby

We have a statistical database for our Facebook application. One of our outputs is Unique Facebook Users based on time range. If our customers select daily usage, we show them a graph of unique Facebook users per hour.
My problem is with the unique values. First, here is the relevant columns from the table:
timestamp---facebookID---actionID---producerID
My current query is:
SELECT HOUR(timestamp) as Hour, COUNT(DISTINCT facebookID) as Events
FROM `e4s_analytic_data`
WHERE actionID = 'ax' AND producerID = '2' AND timestamp BETWEEN'12-06-11 0:00:00' and '12-06-11 23:59:59'
GROUP BY HOUR(timestamp)
This gives unique visitors (Based on facebookID) per hour. But if id = 123 visited in 14 and then visited again in 17, He will be counted twice - firstly in 14 and then in 17.
To solve this I've tried to add an inner query that will give all the ids that are already in the table from earlier hours.
I thought to bring all facebookIDs already listed in the table from 0 (The start of the day) until the current hour (taken from each row from the outside SELECT) and remove them from the outside SELECT. So that every COUNT will only include new Facebook IDs. Here is what I've tried:
SELECT HOUR(timestamp) as Hour, COUNT(DISTINCT facebookID) as Events
FROM `e4s_analytic_data`
WHERE actionID = 'ax' AND producerID = '2' AND timestamp between '12-06-11 0:00:00' and '12-06-11 23:59:59'
AND facebookID NOT IN
( SELECT facebookID FROM `e4s_analytic_data`
WHERE actionID = 'ax' AND producerID = '2' AND
HOUR(timestamp) >= 0 AND HOUR(timestamp) < Hour
)
GROUP BY HOUR(timestamp)
But it gives me this error:
Unknown column 'Hour' in 'where clause'
How can I solve this ?
Thanks.
EDIT: Sample data:
timestamp--------------facebookID--------producerID-------actionID
2012-06-13 12:38:55 ******6513406 2 ax
2012-06-13 08:49:55 ******6513406 2 ax
The query returns 1 unique visitor at 8 and 1 unique visitor at 12. I want to return only 1 unique at 8, because at 12 it is the same visitor from 8.

sql query to get duplicate records with different dates

I need to get records with different date field ,
table Sites:
field id
reference
created
Every day we add lot of records, so I need to do a function that extract all records existing with duplicates of rows just was added, to do some notifications.
the conditions that i can't get is the difference between records of the current day and the old data in the table should be (one day to 4 days) .
If is there any simple query to do that without using transaction .
I'm not sure I totally understand what you mean by duplicate records, but here's a basic date query:
SELECT fieldId, reference, created, DATE(created) as the_date
FROM Sites
WHERE the_date
BETWEEN DATE( DATE_SUB( NOW() , INTERVAL 3 DAY ) )
AND DATE ( NOW() )
I'm making several assumptions such as:
You don't want the "first" row returned
Duplicates don't carry the
date forward (The next after initial 4 days is not a duplicate)
The 4 days means +4 days so Day 5 is included
So, my code is :
with originals as (
select s1.*
from sites as s1
where 0 = (
select count(*)
from sites as s2
where s1.field_id = s2.field_id
and s1.reference = s2.reference
and s1.created <> s2.created
and DATEDIFF(DAY,s2.created, s1.created) between 1 and 4
)
)
select s1.*
from sites as s1
inner join originals as o
on s1.field_id = o.field_id
and s1.reference = o.reference
and s1.created <> o.created
where DATEDIFF(DAY,o.created, s1.created) between 1 and 4
order by 1,2,3;
Here it is in a fiddle: http://sqlfiddle.com/#!3/9b407/20
This could be simpler if some conditions are relaxed.
thanks a lot for every one who tried to help me ,
i have found this solution after lot of test
SELECT `id`,`reference`,count(`config_id`) as c,`created` FROM `sites`
where datediff(date(current_date()),date(`created`)) < 4
group by `reference`
having c > 1
thanks a lot for your help