I need to know, how do i do this on the fly,
for example i have customers who are in the each different duedate statuses, i want to select MAX (most recent due date) ON LEFT JOIN currently when its join two tables it selects the oldest duedate which is not what i want..
SELECT c.customerid, i.datedue
FROM customers c
LEFT JOIN invoice i
ON i.customerid = c.customerid
WHERE i.datedue <= UNIX_TIMESTAMP()
AND c.status!='d'
GROUP BY i.customerid
ORDER BY i.datedue DESC
LIMIT 0, 1000
You need to use the max() function:
SELECT c.customerid, MAX(i.datedue)
FROM customers c LEFT JOIN invoice i ON i.customerid = c.customerid
WHERE i.datedue <= UNIX_TIMESTAMP() and c.status!='d'
GROUP BY i.customerid
ORDER BY i.datedue DESC
LIMIT 0,1000
This will give you the maximum datedue for each customer.
Related
Finding the city in which the most orders were sent leads to the assignment of the city and the number of orders (the named amount column). I have 2 tables the named Customers and Orders
SELECT Customers.City,count( Orders.OrderID) as amount
FROM voodoo.Customers
inner join voodoo.Orders on Customers.CustomerID=Orders.CustomerID
group by Customers.City
having amount >= all(select count(Orders.OrderID)
from voodoo.Customers
inner join voodoo.Orders on Customers.CustomerID=Orders.CustomerID
group by Customers.City);
tables
You don't need a subquery as you can just order by amount (descending) and limit the result to 1:
SELECT Customers.City, count(Orders.OrderID) as amount
FROM voodoo.Customers INNER JOIN voodoo.Orders
ON Customers.CustomerID=Orders.CustomerID
GROUP BY Orders.OrderID
ORDER BY amount DESC
LIMIT 1;
EDIT: as Thorsten Kettner pointed out, I made a copy & paste error; the correct version would GROUP BY Customers.City.
You are looking for the order count per city, not per order. So, don't group by order, but by city. For the ranking of the cities you can use RANK or DENSE_RANK.
SELECT city, amount
FROM
(
SELECT
c.city,
COUNT(o.orderid) AS amount,
RANK() OVER (ORDER BY COUNT(o.orderid) DESC) AS rnk
FROM voodoo.customers c
INNER JOIN voodoo.orders o ON o.customerid = c.customerid
group by c.city
) counted_and_ranked
WHERE rnk = 1;
I'm trying to determine how many new people made an order in 2018. This looks straight forward enough but there is an error with putting calculated fields in the WHERE statement.
SELECT DISTINCT COUNT(c.customer_id)
FROM Customer c
LEFT JOIN
Orders o ON c.customer_id=o.customer_id
WHERE MIN(order_date) > '2017-12-31'
AND MIN(order_date) < '2019-01-01';
You can achieve this by putting a sequence number to the orders and then selecting the first row for each customer. Although, I'm not really sure why you're performing a count of the orders when you just want to consider the first orders. Nevertheless the below should work just fine.
SELECT count(res.customer_id) FROM (
SELECT c.customer_id,
ROW_NUMBER() OVER (PARTITION BY c.customer_id ORDER BY o.order_date ASC) row_num
FROM Customer c
LEFT JOIN Orders o ON c.customer_id=o.customer_id
WHERE o.order_date > '2017-12-31'
AND o.order_date < '2019-01-01'
) res WHERE res.row_num=1
Join with a subquery that finds the customers that were new in 2018.
SELECT COUNT(DISTINCT o.customer_id)
FROM Orders o
JOIN (
SELECT DISTINCT customer_id
FROM Orders
GROUP BY customer_id
HAVING MIN(order_date) > '2017-12-31'
) o1 ON o1.customer_id = o.customer_id
WHERE o.order_date < '2019-01-01';
There's also no need to join with Customers, since the customer ID is in Orders.
And the correct way to get the distinct count is COUNT(DISTINCT o.customer_id), not DISTINCT COUNT(o.customer_id).
I try to obtain a list of all customers my company has not had any assignments for in the last year.
SELECT MAX(assignment_date), full_name
FROM assignments
CROSS JOIN customers
WHERE assignments.customer_id = customers.id
AND assignment_date < '2017-01-01' -- Dynamic value from backend
GROUP BY full_name
ORDER BY assignment_date DESC
This does not seem to work as intended however, since it only returns some customers we did have assignments for in that timeframe. How would I go about implementing such a feature?
Try this code:
SELECT MAX(assignment_date), full_name
FROM customers
where id not in (SELECT id FROM customers inner join assigments on customers.id = assignments.customer_id WHERE assignment_date > '2017-01-01' )
This will return all customers in your database and remove all of them who did have assigments in last year. You should get all customers without assigments before '2017-01-01' as a result
left join customers to assignments where assignments.customer_id IS NULL
and assignment_date greater than '2017-01-01' i.e.
SELECT MAX(assignment_date), full_name
FROM assignments
WHERE assignments.customer_id IN
(SELECT customers.id
FROM customers
LEFT JOIN assignments ON assignments.customer_id = customers.id
WHERE assignments.customer_id IS NULL
AND assignment_date > '2017-01-01')
GROUP BY full_name
ORDER BY assignment_date DESC
I would suggest left join, group by and having:
SELECT MAX(assignment_date), full_name
FROM customers c LEFT JOIN
assignments a
ON a.customer_id = c.id
GROUP BY c.full_name
HAVING MAX(a.assignment_date) < '2017-01-01' OR
MAX(a.assignment_date) IS NULL
ORDER BY MAX(assignment_date) DESC;
It seems you want to show all customers with their last assignment date, but you want to restrict that list to customers that had no assignment since 2017-01-01. This means the dates you will be showing will be null for those customers who had never had an assignment and a date before 2017-01-01 for the others.
So outer join the last dates to the customers and only keep the rows where that date is before 2017-01-01 or null:
select c.full_name, a.max_date
from customers c
left join
(
select customer_id, max(assignment_date) as max_date
from assignments
group by customer_id
) a on a.customer_id = c.customer_id
where a.max_date < date '2017-01-01'
or a.max_date is null
order by a.max_date desc;
Here is three table, order, order_record, pay, with near 2300000 records.
there will be more than 1 record in pay table when giving 1 order_id, so I need to use DISTINCT to remove repeated result
now I need to get distinct data from those three table join on order_id, the example query sql below:
SELECT
DISTINCT (a.order_id)
a.order_id,a.user_id
b.boss_order_id,
c.pay_id,
FROM order a
LEFT JOIN order_record b ON a.order_id = b.order_id AND b.is_delete IN (0,1)
LEFT JOIN pay c ON a.order_id = c.order_id AND c.is_delete =0 WHERE 1=1 AND a.is_delete IN (0,1)
ORDER BY a.id DESC LIMIT 0, 10
this query will takes plenty of time.
then I change to use "GROUP BY":
SELECT
a.order_id,a.user_id
b.boss_order_id,
c.pay_id,
FROM order a
LEFT JOIN order_record b ON a.order_id = b.order_id AND b.is_delete IN (0,1)
LEFT JOIN pay c ON a.order_id = c.order_id AND c.is_delete =0 WHERE 1=1 AND a.is_delete IN (0,1)
GROUP BY a.order_id
ORDER BY a.id DESC LIMIT 0, 10
this time the query takes 122 seconds.
Is there any faster way to implement?
You are using a left join. Hence, you can do:
SELECT o.order_id, o.user_id, orr.boss_order_id, p.pay_id,
FROM (SELECT o.*
FROM order o
WHERE o.is_delete IN (0, 1)
ORDER BY o.id DESC
LIMIT 10
) o LEFT JOIN
order_record orr
ON o.order_id = orr.order_id AND
orr.is_delete IN (0, 1) LEFT JOIN
pay p
ON o.order_id = p.order_id AND
p.is_delete = 0
WHERE 1=1 AND o.is_delete IN (0, 1)
GROUP BY o.order_id
ORDER BY o.id DESC
LIMIT 0, 10
You are using GROUP BY incorrectly, because you have unaggregated columns in the SELECT that are not in the GROUP BY.
Another approach let a where clause do most the work:
select ...
from order
left join order_using using (order_id)
...
where
order.order_id < (select max(order_id) from orders order by order_id limit 10) ...
limit 10
The final limit 10 is weird though as you may get partial records from an order if you drop the group by. I.e. you probably want to drop it and and just put a limit orders table. With the group by means you will a random data from table b and c unless you use aggregate function to tell mysql which of the row values you want.
I have this MySql query:
SELECT *
FROM Customer c
JOIN eHRDemographic ehD ON ehD.CxID = c.CustomerID
JOIN CustPrimaryWeight cpW ON cpW.CxID = c.CustomerID
WHERE c.CustomerID =22703
GROUP BY c.CustomerID
ORDER BY cpW.CustPrimaryWeightID DESC
This doesn't really work correctly as the CustPrimaryWeight table has multiple entries and it's simply joining the first entry and not the more recent one as the ORDER statement doesn't seem to do anything.
Any ideas?
Would http://dev.mysql.com/doc/refman/5.1/en/example-maximum-column-group-row.html help you?
I'm not quite sure what you're trying to do. If you want to sort the CustPrimaryWeight table before the join you can try something like this.
SELECT *
FROM Customer c
JOIN eHRDemographic ehD ON ehD.CxID = c.CustomerID
JOIN (SELECT * FROM CustPrimaryWeight ORDER BY CustPrimaryWeightID DESC) cpW ON cpW.CxID = c.CustomerID
WHERE c.CustomerID =22703
GROUP BY c.CustomerID
But since you're grouping by CustomerID, I think you are trying to show the maximum CustPrimaryWeight data for each customer.
SELECT *
FROM Customer c
JOIN eHRDemographic ehD ON ehD.CxID = c.CustomerID
JOIN (SELECT * FROM CustPrimaryWeight
WHERE CustPrimaryWeightID = (SELECT MAX(CustPrimaryWeightID)
FROM CustPrimaryWeight
WHERE CustomerID = c.CustomerID)
) cpW ON cpW.CxID = c.CustomerID
WHERE c.CustomerID =22703
GROUP BY c.CustomerID