Show values even if empty - mysql

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.

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

How to transform a NOT IN into a LEFT JOIN (or a NOT EXISTS)

I have the following query that is quite complex and even though I tried to understand how to do using various sources online, all the examples uses simple queries where mine is more complex, and for that, I don't find the solution.
Here's my current query :
SELECT id, category_id, name
FROM orders AS u1
WHERE added < (UTC_TIMESTAMP() - INTERVAL 60 SECOND)
AND (executed IS NULL OR executed < (UTC_DATE() - INTERVAL 1 MONTH))
AND category_id NOT IN (SELECT category_id
FROM orders AS u2
WHERE executed > (UTC_TIMESTAMP() - INTERVAL 5 SECOND)
GROUP BY category_id)
GROUP BY category_id
ORDER BY added ASC
LIMIT 10;
The table orders is like this:
id
category_id
name
added
executed
The purpose of the query is to list n orders (here, 10) that belong in different categories (I have hundreds of categories), so 10 category_id different. The orders showed here must be older than a minute ago (INTERVAL 60 SECOND) and never executed (IS NULL) or executed more than a month ago.
The NOT IN query is to avoid treating a category_id that has already been treated less than 5 seconds ago. So in the result, I remove all the categories that have been treated less than 5 seconds ago.
I've tried to change the NOT IN in a LEFT JOIN clause or a NOT EXISTS but the switch results in a different set of entries so I believe it's not correct.
Here's what I have so far :
SELECT u1.id, u1.category_id, u1.name, u1.added
FROM orders AS u1
LEFT JOIN orders AS u2
ON u1.category_id = u2.category_id
AND u2.executed > (UTC_TIMESTAMP() - INTERVAL 5 SECOND)
WHERE u1.added < (UTC_TIMESTAMP() - INTERVAL 60 SECOND)
AND (u1.executed IS NULL OR u1.executed < (UTC_DATE() - INTERVAL 1 MONTH))
AND u2.category_id IS NULL
GROUP BY u1.category_id
LIMIT 10
Thank you for your help.
Here's a sample data to try. In that case, there is no "older than 5 seconds" since it's near impossible to get a correct value, but it gives you some data to help out :)
Your query is using a column which doesn't exist in the table as a join condition.
ON u1.domain = u2.category_id
There is no column in your example data called "domain"
Your query is also using the incorrect operator for your 2nd join condition.
AND u2.executed > (UTC_TIMESTAMP() - INTERVAL 5 SECOND)
should be
AND u2.executed < (UTC_TIMESTAMP() - INTERVAL 5 SECOND)
as is used in your first query

select users, then sum and count that user

I have these two query, the first I look for the users, who have transactions in the last two months the second I sum and tell these users, but with all transactions of all time, the question is how do to assemble this query, first I look and then sum and tell?
SELECT DISTINCT(id_ju1) from master where fecha_registro > DATE_SUB(NOW(), INTERVAL 2 MONTH)
SELECT sum(precio) / count(DISTINCT(id_ju1)) AS TOTAL FROM master
You can do it in one query:
SELECT sum(m.precio) / count(DISTINCT(m.id_ju1)) AS TOTAL FROM master m
WHERE EXISTS (SELECT * FROM master m1 WHERE m1.fecha_registro > DATE_SUB(NOW(), INTERVAL 2 MONTH)
AND m.id_ju1=m1.id_ju1)

Operation With SQL and Date

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.