uso - Ayuda de la declaración SQL: seleccione la última orden para cada cliente
update sql output (7)
Algo como esto debería hacerlo:
SELECT X.*, Y.LatestOrderId
FROM Customer X
LEFT JOIN (
SELECT A.Customer, MAX(A.OrderID) LatestOrderId
FROM Order A
JOIN (
SELECT Customer, MAX(EntryTime) MaxEntryTime FROM Order GROUP BY Customer
) B ON A.Customer = B.Customer AND A.EntryTime = B.MaxEntryTime
GROUP BY Customer
) Y ON X.Customer = Y.Customer
Esto supone que dos pedidos para el mismo cliente pueden tener el mismo Tiempo de entrada, razón por la cual MAX(OrderID)
ID de pedido MAX(OrderID)
se utiliza en la sub consulta Y
para garantizar que solo se produzca una vez por cliente. El LEFT JOIN
se usa porque usted indicó que deseaba mostrarle a todos los clientes: si no han recibido ningún pedido, entonces Latest IdRed será NULL
.
¡Espero que esto ayude!
-
ACTUALIZACIÓN :-) Esto muestra solo clientes con pedidos:
SELECT A.Customer, MAX(A.OrderID) LatestOrderId
FROM Order A
JOIN (
SELECT Customer, MAX(EntryTime) MaxEntryTime FROM Order GROUP BY Customer
) B ON A.Customer = B.Customer AND A.EntryTime = B.MaxEntryTime
GROUP BY Customer
Digamos que tengo 2 tablas: clientes y pedidos. Un cliente puede tener muchos pedidos.
Ahora, necesito mostrarles a los clientes su último pedido. Esto significa que si un cliente tiene más de un pedido, muestre solo el pedido con el último horario de entrada.
Esto es lo lejos que me las arreglé solo:
SELECT a.*, b.Id
FROM Customer a INNER JOIN Order b ON b.CustomerID = a.Id
ORDER BY b.EntryTime DESC
Esto, por supuesto, devuelve a todos los clientes con uno o más pedidos, mostrando primero el último pedido para cada cliente, que no es lo que yo quería. Mi mente estaba atascada en este punto, así que espero que alguien pueda señalarme en la dirección correcta.
Por alguna razón, creo que necesito usar la sintaxis MAX en alguna parte, pero me escapa ahora mismo.
ACTUALIZACIÓN: Después de leer algunas respuestas aquí (¡hay muchas!), Me di cuenta de que cometí un error: me refería a cualquier Cliente con su último registro. Eso significa que si él no tiene una Orden, entonces no necesito enumerarlo.
ACTUALIZACIÓN2: Se arregló mi propia instrucción SQL, que probablemente causó confusión sin fin a los demás.
Algo como:
SELECT
a.*
FROM
Customer a
INNER JOIN Order b
ON a.OrderID = b.Id
INNER JOIN (SELECT Id, max(EntryTime) as EntryTime FROM Order b GROUP BY Id) met
ON
b.EntryTime = met.EntryTime and b.Id = met.Id
Aunque veo que ya has aceptado una respuesta, creo que esta es un poco más intuitiva:
select a.*
,b.Id
from customer a
inner join Order b
on b.CustomerID = a.Id
where b.EntryTime = ( select max(EntryTime)
from Order
where Id = b.Id
);
Tendría que ejecutar algo como esto a través de un plan de ejecución para ver la diferencia en la ejecución, pero cuando la función TOP se realiza después del hecho y que usar "ordenar por" puede ser costoso, creo que usar max (EntryTime) sería la mejor manera de ejecutar esto.
No creo que desee utilizar MAX () ya que no desea agrupar el OrderID. Lo que necesita es una sub consulta ordenada con SELECT TOP 1.
select *
from Customers inner join Orders
on Customers.CustomerID = Orders.CustomerID
and OrderID = (SELECT TOP 1 subOrders.OrderID
FROM Orders subOrders
WHERE subOrders.CustomerID = Orders.CustomerID
ORDER BY subOrders.OrderDate DESC)
Puedes usar una función de ventana.
SELECT *
FROM (SELECT a.*, b.*,
ROW_NUMBER () OVER (PARTITION BY a.ID ORDER BY b.orderdate DESC,
b.ID DESC) rn
FROM customer a, ORDER b
WHERE a.ID = b.custid)
WHERE rn = 1
Para cada cliente (a.id) ordena todos los pedidos y descarta todo excepto el último. La cláusula ORDER BY incluye la fecha de pedido y la identificación de entrada, en caso de que haya varias órdenes en la misma fecha.
En general, las funciones de ventana son mucho más rápidas que cualquier búsqueda utilizando MAX () en una gran cantidad de registros.
Un enfoque que aún no he visto arriba:
SELECT
C.*,
O1.ID
FROM
dbo.Customers C
INNER JOIN dbo.Orders O1 ON
O1.CustomerID = C.ID
LEFT OUTER JOIN dbo.Orders O2 ON
O2.CustomerID = C.ID AND
O2.EntryTime > O1.EntryTime
WHERE
O2.ID IS NULL
Esto (al igual que las otras soluciones, creo) supone que no hay dos pedidos para el mismo cliente que puedan tener exactamente el mismo tiempo de entrada. Si eso es una preocupación, entonces tendría que hacer una elección en cuanto a qué determina cuál es el "último". Si eso es una preocupación publica un comentario y puedo expandir la consulta si es necesario para dar cuenta de eso.
El enfoque general de la consulta es encontrar el pedido para un cliente donde no hay otro pedido para el mismo cliente con una fecha posterior. Es entonces el último orden por definición. Este enfoque a menudo ofrece un mejor rendimiento que el uso de tablas o subconsultas derivadas.
SELECT Cust.*, Ord.*
FROM Customers cust INNER JOIN Orders ord ON cust.ID = ord.CustID
WHERE ord.OrderID =
(SELECT MAX(OrderID) FROM Orders WHERE Orders.CustID = cust.ID)