Operation With SQL and Date - mysql

I'm a newbye in the operation with SQL on date.
However,I need to do a query that return record filter by X date < or > of 30 days or similar.
I have this query for now:
SELECT nome_prodotto,quantita
FROM prodotti
LEFT JOIN acquisti
ON prodotti.id_prodotto = acquisti.id_prodotto
my goal is get the product that aren't bought in last 30 days or similar

WHERE DATE_SUB(CURDATE(),INTERVAL 30 DAY) =< your_date;

If the date field in acquisti is called date_acquisti, products not bought in the last 30 days will be queried like this:
SELECT nome_prodotto,quantita
FROM prodotti
LEFT JOIN acquisti
ON (prodotti.id_prodotto = acquisti.id_prodotto
AND acquisti.date_acquisti > CURDATE() - INTERVAL 30 DAY)
where acquisti.id_prodotto is NULL
The trick is using the JOIN condition to get only the product acquisitions in the last 30 days. Since this is a LEFT JOIN, any row in result set where acquisti.id_prodotto is NULL means the product was not purchased in that period.

You can use date_add function to achieve this
Ex:
x_date between DATE_ADD(NOW(), INTERVAL -1 MONTH) and NOW()

Also,
where myDate between some_date and some_other_date
may help you in other similar situations.

Related

MySQL query to find items ordered at least once that have not been ordered lately

I simplified the query and the table, but to give you some context: I have an "orders" table that contains all the items ordered by customers.
I want to check which items have been ordered at least once in history, but then, for whatever reason, nobody ordered them anymore (in this case, 180 days but it's just an example).
SELECT DISTINCT (idItem)
FROM orders
WHERE myDate < DATE_SUB(NOW(),INTERVAL 180 DAY)
AND
(idItem NOT IN
(SELECT
DISTINCT(idItem)
FROM orders
WHERE myDate > DATE_SUB(NOW(),INTERVAL 180 DAY)
)
)
ORDER BY myDate
This was my reasoning: I pick all the items ordered MORE THAN 6 months ago, and from the result I keep only the ones that DO NOT APPEAR in the previous 6 months.
I have 2 problems: one, it gives me back basically all of them, and second, regardless of "distinct", I still get plenty of duplicates :(
I do not usually deal with SQL, I know enough for simple queries but this one is probably as complex as I can make them :)
SELECT idItem
FROM orders
GROUP BY idItem
HAVING 0 = SUM(myDate > (CURRENT_DATE - INTERVAL 180 DAY))
?
With NOT EXISTS:
SELECT DISTINCT o.idItem
FROM orders o
WHERE NOT EXISTS (
SELECT 1 FROM orders
WHERE idItem = o.idItem AND myDate > DATE_SUB(NOW(), INTERVAL 180 DAY)
)

MySQL get latest 7 days reservations, grouped by NameResource

I'm tring to write a query, without a good resultset.
I would to retreive a Number of reservations in last 7 days.
Grouped by NameOfResource.
When i'm tring to set a WHERE clause like this prenotazioni.Data >= CURDATE() - INTERVAL 7 DAY
I get only NameOfResource with reservations in latest 7 days,
but not the rooms without reservations.
My Query was like that: (without WHERE the result is good)
SELECT count(*) as NReservationsFromWeek,Nomeroom FROM reservations
INNER JOIN room ON reservations.FKRoom = room.IDRoom
WHERE reservations.Data >= CURDATE() - INTERVAL 7 DAY
group by room.IDRoom
Thank you to explain me where I was wrong.
You can use a LEFT JOIN, if you want all rooms, even those with a count of 0:
SELECT ro.IDRoom, ro.Nomeroom, COUNT(re.FKRoom) as NReservationsFromWeek,
FROM room ro LEFT JOIN
reservations re
ON re.FKRoom = ro.IDRoom AND
re.Data >= CURDATE() - INTERVAL 7 DAY
GROUP BY ro.IDRoom, ro.Nomeroom; -- Both unaggregated keys should be in the GROUP BY

Selecting multiple values within a timestamp interval

I have a (MySQL) table that looks like this:
`radiostation_id` varchar(36) NOT NULL,
`song_id` varchar(36) NOT NULL,
`date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`length` int(4) NOT NULL
What I want to do is to find every same song_id that has been played within an interval of 15 minutes. It could be that the song was played for example today 15:10 and then again 15:20. So it shouldnt be that i need to set the interval myself, it should check for any interval through the table and list all the songs and timestamps it happened.
It seems to me that you want a song that is played within a certain 15 minutes regardless of the day. There are date and time functions you can use to parse the information you want. For example, you can use TIME() to extract the time portion of your column. For example, you can search for any song played between 12:00 and 12:15 like this:
SELECT DISTINCT id
FROM myTable
WHERE TIME(timeColumn) BETWEEN '12:00:00' AND '12:15:00';
Here is a little SQL Fiddle I used to try it.
EDIT
Based on our discussions in the comments, you can use the following query. It will self join the table on the condition that the song_id matches (so you can compare individual songs), the condition that the time is not exactly the same (so no occurrence is counted twice) and on the condition that the interval in the second table is within +/- 15 minutes of the first like this:
SELECT m.song_id, m.timecolumn
FROM myTable m
JOIN myTable mt
ON m.song_id = mt.song_id
AND m.timeColumn != mt.timeColumn
AND mt.timeColumn BETWEEN DATE_SUB(m.timeColumn, INTERVAL 15 MINUTE) AND DATE_ADD(m.timeColumn, INTERVAL 15 MINUTE);
Here is an updated Fiddle.
It's not entirely clear what you are asking.
If you want to find occurrences of the same song_id, where a second row with the same song_id has a date value within 15 minutes of the first row, one way to get that would be a query like this:
SELECT t.song_id
FROM looks_like_this t
WHERE EXISTS ( SELECT 1
FROM looks_like_this s
WHERE s.song_id = t.song_id
AND s.date >= t.date
AND s.date <= t.date + INTERVAL 15 MINUTE
AND NOT (s.radiostation_id = t.radiostation_id AND s.date = t.date)
If you want to return a unique list of song_id, then add either DISTINCT keyword or a GROUP BY t.song_id clause.
Another way to get the result would be use a JOIN operation:
SELECT t.song_id
FROM looks_like_this t
JOIN looks_like_this s
ON s.song_id = t.song_id
AND s.date >= t.date
AND s.date <= t.date + INTERVAL 15 MINUTE
AND NOT (s.radiostation_id = t.radiostation_id AND s.date = t.date)
GROUP BY t.song_id
The following will show you all the rows where the last played is in the last 15 minutes.
SELECT * FROM myTable
WHERE date>= NOW() - INTERVAL 15 MINUTE
Note that using date in a table column is bad practice as it is a reserved mysql word.
You just need to list out all the songs, when they were played and connect to the same song if it was played again within 15 minutes later.
select pt1.ID, pt1.StartDate, pt2.StartDate StartDate2
from PlayTimes pt1
join PlayTimes pt2
on pt2.ID = pt1.ID
and pt2.StartDate > pt1.StartDate
and pt2.StartDate <= Date_Add( pt1.StartDate, interval 15 minute );
You didn't mention if the radio station played any role. The query above will return a song if it was play again within 15 minutes even on a different station. This makes sense. If you need only those songs played again within 15 minutes on the same station, then add the station id to the join criteria. Would a station ever do that (play the same song twice within 15 minutes)? Or are you checking to make sure a station never does that?

Mysql - Find increased value over a week

Score Table
user_idx (int)
date (datetime)
score (int)
I need to find out how much total score has increased over a week from today's date. I know that I need two of the same user tables grouped by user_idx that one contains total scores from the past to today and the other contains total scores from the past to a date of a week ago.
After that, by substracting one from the other will give me the answer... but I'm struggling to write effective sql query that does it.
I've tried
SELECT BLAH BLAH
FROM (SELECT user_idx, COUNT(*) as last_week_study_amount
FROM user_table
WHERE date <= date_sub(now(),INTERVAL 1 WEEK)
GROUP BY user_idx)
AS a WHERE .....
Could you help me :( ?
Let me clear you want to get total count in last week.
Try below query
SELECT *
FROM (SELECT user_idx, COUNT(*) as last_week_study_amount
FROM user_table
WHERE date <= date_sub(now(),INTERVAL 1 WEEK)
GROUP BY user_idx)
AS a WHERE .....
SELECT (SUM(score) - last_week_score) AS increased_score,
FROM user a
JOIN (SELECT b.user_idx, COUNT(*) as last_week_score
FROM userb
WHERE date<= date_sub(now(),INTERVAL 1 WEEK)
GROUP BY b.user_idx) As c ON a.user_idx = c.user_idx
WHERE DATE(date) <= DATE(NOW())
GROUP BY a.user_idx
I ended up writing this code and I think this one is working okay... not sure if it's the best or has a critical error. I will update it if it turns out to be a bad one...

Show values even if empty

I am using the following to show a count of products added over the last 7 days...Can i somehow tailor the query to show all the last 7 days even if COUNT=0?
query as it stands:
SELECT DAYNAME(dateadded) DAY, COUNT(*) COUNT
FROM `products`
WHERE (`dateadded` BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND CURDATE() && site_url = 'mysite.com')
GROUP BY DAY(dateadded)
Add a table with dates in it (a dates lookup table), then:
SELECT DAYNAME(d.FullDate) DAY, COUNT(*) COUNT
FROM dates d
LEFT OUTER JOIN products p ON d.FullDate = DATE(p.dateadded)
AND p.site_url = 'mysite.com'
WHERE d.FullDate BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND CURDATE()
GROUP BY d.FullDate
It takes a little bit of storage, yes, but it will make queries like this a lot easier.
Alternatively, you can make a stored procedure that loops through dates between 7 days ago and today and returns one row for each.