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
Related
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;
Here are 4 tables....
tbl_std_working_hour
tbl_attendance
tbl_holiday
tbl_leave
I want to find out the employees absentee reports by this query....but it takes times when I have applied this for many employees...is there any way to simplify this query?
SELECT date
FROM tbl_std_working_hour
WHERE date NOT IN (SELECT date FROM tbl_attendance WHERE emp_id = '$emp_id')
AND date NOT IN (SELECT date FROM tbl_holiday)
AND date NOT IN (SELECT date FROM tbl_leave WHERE emp_id = '$emp_id')
AND total_hour <> '00:00:00'
AND date >= '$start'
AND date <= '$end'
AND emp_id = '$emp_id'
First, I would rewrite using NOT EXISTS:
SELECT wh.date
FROM tbl_std_working_hour wh
WHERE NOT EXISTS (SELECT 1
FROM tbl_attendance a
WHERE a.date = wh.date AND a.emp_id = wh.emp_id
) AND
NOT EXISTS (SELECT 1
FROM tbl_holiday h
WHERE h.date = wh.date
) AND
NOT EXISTS (SELECT 1
FROM tbl_leave l
WHERE l.emp_id = wh.emp_id and l.date = wh.date
)
WHERE wh.total_hour <> '00:00:00' AND
wh.date >= '$start' AND
wh.date <= '$end' AND
wh.emp_id = '$emp_id';
Then add the following composite (multi-column) indexes:
tbl_std_working_hour(emp_id, date, total_hour)
tbl_attendance(emp_id, date)
tbl_holiday(date) (might already exist if date is the primary key or unique)
tbl_leave(emp_id) (might already exist if emp_id is the primary key or unique)
Note that I changed the subqueries to refer to the emp_id in the outer query. This makes it easier to change the emp_id. In addition, your query should be using parameters for the values in the WHERE clause.
This is also a better way that can work better using UNION ALL
SELECT date
FROM tbl_std_working_hour AS tswh
WHERE NOT EXISTS(
SELECT date FROM tbl_attendance ta WHERE ta.date = tswh.date AND ta.emp_id = tswh.emp_id
UNION ALL
SELECT date FROM tbl_holiday th WHERE th.date = tswh.date
UNION ALL
SELECT date FROM tbl_leave tl WHERE tl.date = tswh.date AND tl.emp_id = tswh.emp_id)
AND total_hour <> '00:00:00'
AND date >= '$start'
AND date <= '$end'
AND emp_id = '$emp_id'
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';
I'd like to select only the nearest date in the past and all the dates in the future.
I reach a result with the following query, but the results are side by side instead row per row.
How should I modifiy my query?
SELECT t1.*, t2.*
FROM
(SELECT *
FROM table1
WHERE from_p <= NOW()
AND prod = 3000
ORDER BY from_p DESC
LIMIT 1) AS t1
JOIN
(SELECT *
FROM table1
WHERE from_p >= NOW()
AND prod = 3000
ORDER BY from_p DESC
) AS t2
You need a use a subquery to first find "latest past date" and then write the main query based on that:
SELECT * FROM table1
WHERE from_p >= (
SELECT from_p FROM table1
WHERE from_p <= NOW() AND prod=3000
ORDER BY from_p DESC LIMIT 1
)
AND prod=3000
ORDER BY from_p;
Try:
(SELECT *
FROM table1
WHERE from_p <= NOW()
AND prod = 3000
ORDER BY from_p DESC
LIMIT 1)
UNION
(SELECT *
FROM table1
WHERE from_p >= NOW()
AND prod = 3000
ORDER BY from_p DESC)
assume we have table
id, title, date
I need to build 1 query to:
select date = TODAY, order by id
select data < TODAY, order by date desc,
select data > TODAY, order by date asc,
I think you need to use UNION and sub queries:
SELECT * FROM (
SELECT *
FROM YourTable
WHERE Date(dateField) = Date(Now())
ORDER BY ID
) t1
UNION
SELECT * FROM (
SELECT *
FROM YourTable
WHERE dateField < Now()
ORDER BY dateField DESC
) t2
UNION
SELECT * FROM (
SELECT *
FROM YourTable
WHERE Date(dateField) > Now()
ORDER BY dateField
) t3
Here is a simplified SQL Fiddle example.
Good luck.