MySQL Query NOT IN another Query - mysql

SELECT DISTINCT d.customer_id, d.date_added FROM `order` d
WHERE d.customer_id NOT IN (
SELECT DISTINCT i.customer_id
FROM `order` i
WHERE i.date_added > '2015-02-15 14:00:00'
)
ORDER BY d.date_added DESC;
The above query should return customer_id of customers who have not ordered after 15 Feb 2015 (I think). But very first record is
17168, 2015-08-16 17:36:00
What am I doing wrong?
This below query
SELECT DISTINCT i.customer_id,i.date_added FROM `order` i
WHERE i.date_added > '2015-02-15 14:00:00'
ORDER BY i.date_added ASC;
returns expected result i.e. list of customer ids for orders placed after 15 Feb
P.S. customer_id can not be NULL

Can customer_id or data_added be NULL? Try
SELECT DISTINCT d.customer_id,d.date_added
FROM order d
WHERE d.customer_id NOT IN
(SELECT DISTINCT i.customer_id FROM order i
WHERE i.date_added > '2015-02-15 14:00:00'
and customer_id IS NOT NULL
and i.date_added IS NOT NULL)
ORDER BY d.date_added DESC;
Edit
The way you wrote your query will get you customer_ids with an order before '2015-02-15 14:00:00'. But if the customer ordered something after this date they might be in the resultset.
Edit2
Why not write
SELECT DISTINCT customer_id, date_added
FROM order
WHERE date_added <= '2015-02-15 14:00:00'
ORDER BY date_added DESC;

I would use a correlated not exists query to exclude all customers that have any order after the specified date:
SELECT o1.customer_id, o1.date_added
FROM `order` o1
WHERE NOT EXISTS (
SELECT 1
FROM `order` o2
WHERE date_added > '2015-02-15 14:00:00'
AND o1.customer_id = o2.customer_id
)
ORDER BY o1.date_added DESC;

If you want customers who have not ordered since a certain date, I would just use group by and having:
SELECT o.customer_id, MAX(o.date_added) as most_recent
FROM `order` o
GROUP BY o.customer_id
HAVING MAX(o.date_added) <= '2015-02-15 14:00:00';

Related

MYSQL select sum by months including with null values

I'm working on a mysql request that make the sum of values by months including those with null values.
The request result send only the first line without making the sum operation.
SELECT SUM(IFNULL(t1.sub_total,0)) AS amount,
am.a_month AS date
FROM (
SELECT ifnull(vn.sub_total,0) as sub_total,
cast(DATE_FORMAT(order_date, '%M') as char) as mdate
FROM orders_new vn
WHERE order_status = 1
AND order_date BETWEEN '2022-01-01' AND '2022-12-31'
GROUP BY DATE_FORMAT(order_date, '%M')
) t1
RIGHT OUTER JOIN all_months am on t1.mdate = am.a_month
group by am.a_month
order by a_month_id asc;
result
below the source table
You don't need the GROUP BY clause in the subquery. Your query should be:
SELECT
SUM(IFNULL(t1.sub_total, 0)) AS amount,
am.a_month AS date
FROM
(SELECT
IFNULL(vn.sub_total, 0) AS sub_total,
CAST(DATE_FORMAT(order_date, '%M') AS char) AS mdate
FROM
orders_new vn
WHERE
order_status = 1
AND order_date BETWEEN '2022-01-01' AND '2022-12-31') t1
RIGHT OUTER JOIN
all_months am ON t1.mdate = am.a_month
GROUP BY
am.a_month
ORDER BY
a_month_id ASC;

Getting all orders, where the last order ist older than a year in mySql

I have a mySQL table, which holds:
CustomerId and OrderDate
There can me multiple rows for one CustomerId
Now, I try to get the CustomerId's where only the last OrderDate is older than a year.
I try the following:
SELECT *
FROM order
WHERE OrderDate <=DATE_SUB(now(), Interval 1 Year)
GROUP BY CustomerId
ORDER BY OrderDate DESCC;
The problem here is, that I get all the rows, which are older then 1 year.
But as I said above, I try to get only the latest order, which is older than 1 year.
THX for any advise
Order the rows and limit to the last. Also, you had DESCC instead of DESC.
SELECT *
FROM order
WHERE OrderDate <=DATE_SUB(now(), Interval 1 Year)
GROUP BY CustomerId
ORDER BY OrderDate DESC
LIMIT 1;
You might also try this query:
SELECT
`CustomerId`,
`CustomerName`, // Add other fields you want returned.
MAX(`OrderDate`)
FROM `order`
WHERE `OrderDate` <= DATE_SUB(now(), Interval 1 Year)
GROUP BY `CustomerId`
ORDER BY MAX(`OrderDate`) DESC;
Also, this will return all of the related columns in the last order for each customer:
SELECT *
FROM `order` a
JOIN (
SELECT
`CustomerId`,
MAX(`OrderDate`) as `maxdate`
FROM `order`
WHERE `OrderDate` <= DATE_SUB(now(), Interval 1 Year)
GROUP BY `CustomerId`) b
ON a.`CustomerId` = b.`CustomerId` AND
a.`OrderDate` = b.`maxdate`
ORDER BY `maxdate` DESC;
Try this subquery:
select customer_id
from customer table
where order_id in(Select order_id from (select order_id from order_table (year(now())-year(order_date)) = 1 order by order_date desc limit 1))
if it doesn't work please post your table structure.
THX for all your tips.
At the end, I found my working solution:
SELECT
*
FROM order a1
INNER JOIN (SELECT
order.Id
FROM (SELECT
*
FROM (SELECT
*
FROM order
WHERE OrderDate <= DATE_SUB(NOW(), INTERVAL 1 year)
ORDER BY OrderDate DESC) AS Sub
GROUP BY Sub.CustomerId) AS a2) AS a3
ON a1.id = a3.id;

To find the maximum number of order count that occur in any 1 hour of the day from the database?

I have a food selling website in which there is order table which record the order of every user.It column for user id ,user name,orderid ,timestamp of order.I want to know the maximum number of order that has been made in any one hour span through out the day.Give me any formula for this,or any algorithm or any sql queries for these.
SQL server:
with CTE as
(
select cast(t1.timestamp as date) as o_date, datepart(hh, t1.timestamp) as o_hour, count(*) as orders
from MyTable t1
group by cast(t1.timestamp as date), datepart(hh, t1.timestamp)
)
select o_date, o_hour, orders
from CTE
where orders = (select max(orders) from CTE)
Oracle
with CTE as
(
select to_char(t1.timestamp, 'YYYYMMDD') as o_date, to_char(t1.timestamp, 'HH24') as o_hour, count(*)
from MyTable t1
group by to_char(t1.timestamp, 'YYYYMMDD'), to_char(t1.timestamp, 'HH24')
)
select o_date, o_hour, orders
from CTE
where orders = (select max(orders) from CTE)
You can get count by day and hour like this
For SQL
SELECT TOP 1
COUNT(*)
FROM myTable
GROUP BY DATEPART(day, [column_date]), DATEPART(hour, [column_date])
ORDER BY COUNT(*) DESC;
For MySQL
SELECT
COUNT(*)
FROM myTable
GROUP BY HOUR(column_date), DAY(column_date)
ORDER BY COUNT(*) DESC
LIMIT 1;

SQL query for each ID in table

I have a query for 1 particular customer_id. How can I execute this query for each customer_id in table?
SELECT *
FROM table
WHERE date <= '2015-12-31 23:59:59' AND customer_id = 100
ORDER BY date DESC
LIMIT 1
You can use NOT EXISTS():
SELECT * FROM YourTable t
WHERE t.date <= '2015-12-31 23:59:59'
AND NOT EXISTS(SELECT 1 FROM YourTable s
WHERE t.customer_id = s.customer_id
AND t.date < s.date)
This will select only a record after the date filter where NOT EXISTS another record for the same id with a bigger date. Its basically the same as limit 1 for all.
You can use Inner join:
SELECT * FROM YourTable t INNER JOIN
(SELECT * FROM Table) s
ON t.customer_id = s.customer_id
WHERE t.date = '2015-12-31 23:59:59'
ORDER BY date DESC

How can i get count of customers per day by unique and repeat customer for specific date?

I am trying to get a result from my order table to get list of counts of customers who 1st time ordered and repeat orders. Something like below.
Date 1st time time repeat order
2014-09-01 43 90
2014-09-02 3 45
2014-09-03 12 30
2014-09-04 32 0
2014-09-05 1 98
I am beginner in sql and i ma using mysql.
My table structure is like.
OrderNumber int
OrderDate datetime
CustomerID int
I have tried this query in mysql but it only gives me first timed ordered count.
SELECT DATE(OrderDate), COUNT(*)
FROM orders T JOIN (
SELECT MIN(OrderDate) as minDate, CustomerID
FROM orders
GROUP BY CustomerID) T2 ON T.OrderDate = T2.minDate AnD T.CustomerID = T2.CustomerID
GROUP BY DATE(T.OrderDate)
You can get the total orders per day by grouping on OrderDate:
SELECT OrderDate, COUNT(OrderNumber) AS total FROM orders GROUP BY OrderDate
And you can get the no. of first orders per day from the following query :
SELECT OrderDate, COUNT(q1.CustomerID) AS first FROM (SELECT CustomerID, min(OrderDate) AS OrderDate FROM orders GROUP BY CustomerID)q1 GROUP BY q1.OrderDate
Now join these two on OrderDate to get the distribution of first and repeated orders :
SELECT a.OrderDate, a.first, (b.total - a.first) AS repeated FROM
(SELECT OrderDate, COUNT(q1.CustomerID) AS first FROM (SELECT CustomerID, min(OrderDate) AS OrderDate FROM orders GROUP BY CustomerID)q1 GROUP BY q1.OrderDate)a
JOIN
(SELECT OrderDate, COUNT(OrderNumber) AS total FROM orders GROUP BY OrderDate)b
on(a.OrderDate = b.OrderDate)
A slightly complicated query but this should do:
First Time Users: Just Group by customerID to get the min orderdate and then group by on that date to get the number of new users on a particular day. Query would look like this:
select date(mdate) as day, COUNT(*) from (select customerid, min(orderdate) as mDate from orders GROUP BY CustomerID)q1 GROUP BY day;
Repeat Users: First filter out all such orderno which were placed as first orders and then do a group by orderdate to get repeat. Query would be :
select date(orderdate) day, COUNT(*) from (select * from orders where orderno not in (select orders.orderno from orders JOIN (select customerid, min(orderdate) as mdate from orders GROUP BY CustomerID)as order2 ON (orders.customerid = order2.customerid) and (orders.orderdate = order2.mdate))) as q1 GROUP BY day;
You can do a join on day for both these queries to get combined results in a way you mentioned. Let me know if doesn't work
EDIT:
This would be the complete query: Here I am doing a UNION on both left and right outer joins since it might happen that you come across where there are no new requests or no repeated requests. This would take care of both the scenarios.
select q2.*, q3.repeated from (select date(mdate) as day, COUNT(*) as first from (select customerid, min(orderdate) as mDate from orders GROUP BY CustomerID)q1 GROUP BY day) as q2 LEFT OUTER JOIN (select date(orderdate) day, COUNT(*) as repeated from (select * from orders where orderno not in (select orders.orderno from orders JOIN (select customerid, min(orderdate) as mdate from orders GROUP BY CustomerID)as order2 ON (orders.customerid = order2.customerid) and (orders.orderdate = order2.mdate))) as q1 GROUP BY day) as q3 on q2.day = q3.day UNION select q2.*, q3.repeated from (select date(mdate) as day, COUNT(*) as first from (select customerid, min(orderdate) as mDate from orders GROUP BY CustomerID)q1 GROUP BY day) as q2 RIGHT OUTER JOIN (select date(orderdate) day, COUNT(*) as repeated from (select * from orders where orderno not in (select orders.orderno from orders JOIN (select customerid, min(orderdate) as mdate from orders GROUP BY CustomerID)as order2 ON (orders.customerid = order2.customerid) and (orders.orderdate = order2.mdate))) as q1 GROUP BY day) as q3 on q2.day = q3.day
this is my answer but not sure is still can improve.
SELECT userID, COUNT(*) AS repeat_order_cnt FROM
(SELECT DATE(OrderDate) AS order_DT, userID, COUNT(*) AS no_of_order FROM order
AND YEAR(orderDate) = '2015'
AND MONTH(orderDate) = '01'
GROUP BY order_DT,userID) AS order2
GROUP BY userID
HAVING COUNT(*) > 1