Ordering a MySQL query with joins and groups - mysql

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

Related

converting a sql query to subquery

I am trying to determine the customers spending behavior by writing a query to select the top 10 highest spenders.
I have the following query and it works fine:
SELECT c.CustomerID
, SUM(Quantity * UnitPrice) Total_Spent
FROM Orders o
JOIN OrderDetails d
ON d.OrderID = o.OrderID
JOIN Customers c
ON c.CustomerID = o.CustomerID
GROUP
BY c.CustomerID
ORDER
BY Total_Spent
limit 10;
However, I want to create a subquery instead of having this complicated one. I have tried the following but it doesn't work:
SELECT Customers.CustomerID
FROM Customers
JOIN (
SELECT SUM(Quantity *UnitPrice) as Total_Spent
FROM Orders
JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID) Orders
ON Orders.CustomerID = Customers.CustomerID
GROUP BY Customers.CustomerID
ORDER BY Total_Spent
LIMIT 10;
I don't know what the problem is. (I am kinda new in SQL)
You can simplify your query because you don't need the customers table. That and table aliases should make your query simpler:
SELECT o.CustomerID, SUM(od.Quantity * od.UnitPrice) as Total_Spent
FROM Orders o JOIN
OrderDetails od
ON o.OrderID = od.OrderID
GROUP BY o.CustomerID
ORDER BY Total_Spent DESC
LIMIT 10;

Retrieve customer who bought more than 13 different products who never purchased same product

I tried this. But I feel this gives people who ordered same product
SELECT DISTINCT Count(od.orderqty) OrderQty,
c.customerid,
od.productid
FROM sales.customer c
INNER JOIN sales.salesorderheader oh
ON c.customerid = oh.customerid
INNER JOIN sales.salesorderdetail od
ON oh.salesorderid = od.salesorderid
GROUP BY od.productid,
c.customerid
HAVING Count(od.productid) > 10
ORDER BY c.customerid
Not sure what flavor of SQL you're using but try this:
select t.CustomerID
from (
select c.CustomerID
, count(distinct od.ProductID) as DistinctCount
, count(od.ProductID) as Count
from Sales.Customer c
join Sales.SalesOrderHeader oh
on c.customerid = oh.customerid
join Sales.SalesOrderDetail od
on oh.SalesOrderID = od.SalesOrderID
group
by c.CustomerID
) as t
where t.DistinctCount = t.Count
and t.DistinctCount > 13
order
by t.CustomerID

How can I combine information from 4 different tables in a SQL query?

I have a to write an SQL query to list the names and total spend of customers who made more
than one order. The following lists all the relevant information but I'm struggling to see how to move forward with this.
SELECT l.quantity, o.orderID, i.itemID, o.custID, i.unitcost, c.familyname
FROM lineitems l, orders o, items i, customers c
WHERE l.itemID = i.itemID
AND c.custID = o.custID
AND o.orderID = l.orderID
ORDER BY o.custID
Select customerId, Sum(i.quantity*i.unitCost)
From lineitems I
join orders o on o.orderID = i.orderID
where Exists(Select * From orders
where customerId = o.customerId
having count(*) > 1)
group by customerId
or, with name instead of just customerId
Select c.familyname, Sum(i.quantity*i.unitCost)
From lineitems I
join orders o on o.orderID = i.orderID
join customers c on c.customerId = o.customerId
where Exists(Select * From orders
where customerId = o.customerId
having count(*) > 1)
group by c.familyname

Update Query with Correlated Subquery

I'm trying to convert a Foxpro application into .NET. As part of that conversion I'm converting the data from DBF tables to Sql server.
I need to come up with a couple new fields in the Customer table based on the Orders table, FirstOrder and LastOrder.
I just can't seem to muddle through how to do this in TSql. I know how I'd do it in Foxpro, and I could actually still do it there if I had to, but I know I need to learn how to do this in Sql.
Here is the basic structure.
Customer Table has an Id, then the FirstOrder and LastOrder fields I need updated.
Order Table has OrderDate, but here is the real curve. The Customer Id can exist in 5 different fields inside the Order: ShipperId, PickupId, ConsigneeId, DeliveryId, or BillingId.
So something like:
UPDATE customers
SET FirstOrderDate =
(Select MIN(OrderDate)
FROM Orders o
WHERE o.ShipperId = Customers.Id or
o.PickupId = Customers.Id or
o.ConsigneeId = Customers.Id or
o.DeliveryId = Customers.Id or
o.BillingId = Customers.Id)
Just can't seem to find out how to tie the subquery with the main update query.
Thanks,
-Sid
EDIT:
Here's the SELECT that's working based on MarkD's suggestion:
Select C.Id,Min(o.OrderDate) as firstorder, MAX(o.OrderDate) as lastorder
from Customers C
JOIN Orders o
on o.ShipperId = C.Id or
o.PickupId = C.Id or
o.ConsigneeId = C.Id or
o.DeliveryId = C.Id or
o.BillingId = C.Id
GROUP BY C.Id
So now do I use this as a subquery or cursor to post back to the Customers table?
Although I think the JOIN criteria is highly unlikely, it looks like you're trying to do this?
EDIT: I've modified the JOIN criteria but this is what you're after.
Grouping By columns that are OR'd is odd.
;WITH MinOrderDates AS
(
SELECT CustID
,OrderDate = MIN(OrderDate)
FROM Orders
GROUP BY CustID
)
UPDATE C
SET FirstOrderDate = MIN(O.OrderDate)
FROM Customers C
JOIN MinOrderDates O ON C.Id = O.CustID
This is what your query would look like with the ORs
;WITH MinOrderDates AS
(
SELECT ShipperId
,PickupId
,ConsigneeId
,DeliveryId
.BillingId
,OrderDate = MIN(OrderDate)
FROM Orders
GROUP BY ShipperId
,PickupId
,ConsigneeId
,DeliveryId
.BillingId
)
UPDATE C
SET FirstOrderDate = MIN(O.OrderDate)
FROM Customers C
JOIN MinOrderDates O ON o.ShipperId = C.Id or
o.PickupId = C.Id or
o.ConsigneeId = C.Id or
o.DeliveryId = C.Id or
o.BillingId = C.Id
EDIT: Though I am having a hard time finding fault with your posted syntax.
Try this
UPDATE customers
SET FirstOrderDate =
(Select MIN(OrderDate)
FROM Orders
WHERE ShipperId = Customers.Id or
PickupId = Customers.Id or
ConsigneeId = Customers.Id or
DeliveryId = Customers.Id or
BillingId = Customers.Id)

MySQL Join with conditions on join on the fly

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.