Select data based on latest transaction date for each item - sql

I have a query which I want it to list all latest transaction's price for each stock item. I've tried to use MAX() to list all latest transaction for each item without including the price and it works but when I included the price, the method will not work.
Here's my query
SELECT MAX(DocDate) AS DocDate, StockCode, Price
FROM StockPurchasePriceHistory spph
INNER JOIN Stocks s
ON spph.Stock = s.Id
GROUP BY StockCode, Price
ORDER BY StockCode ASC
Output

use row_number
select * from (SELECT row_number()over(partition by StockCode order by DocDate desc) rn
, StockCode, Price
FROM StockPurchasePriceHistory spph
INNER JOIN Stocks s
ON spph.Stock = s.Id
) a where a.rn=1

try this:
SELECT MAX(DocDate) AS DocDate, StockCode, sum(Price) as Price
FROM StockPurchasePriceHistory spph
INNER JOIN Stocks s
ON spph.Stock = s.Id
GROUP BY StockCode
ORDER BY StockCode ASC

This is a good place to use APPLY:
SELECT spph.DocDate, s.StockCode, spph.Price
FROM Stocks s CROSS APPLY
(SELECT TOP (1) spph.*
FROM StockPurchasePriceHistory spph
WHERE spph.Stock = s.Id
ORDER BY spph.DocDate DESC
) spph;
With an index on StockPurchasePriceHistory(Stock, DocDate desc), I would expect this to be a bit faster than alternatives using window functions and approximately as fast as a correlated subquery.

Related

SQL NESTED JOIN NOT USING WHERE

What is the current price of each product? Display product code, product description, unit, and its current price. Always assume that NOT ALL products HAVE unit price BUT you need to display it even if it has no unit price on it. without using WHERE script
Product Table
prodCode
description
unit
PriceHist Table
prodCode
effDate
unitPrice
This is my work... Please Help me to improve my anwswer.
SELECT p.prodCode, p.description, p.unit, MAX(ph.unitPrice) "Current Price"
FROM product p
INNER JOIN priceHist AS ph
ON p.prodCode = ph.prodCode
GROUP BY p.prodCode, p.description, p.unit
ORDER BY MAX(ph.unitPrice);
Someone said I NEED TO USE PRICEHIST TWICE
User window functions and left join:
select . . . -- whatever columns you want
from products p left join
(select ph.*,
row_number() over (partition by p.prodcode order by effdate desc) as seqnum
from pricehist ph
) ph
on ph.prodcode = p.prodcode and ph.seqnum = 1;
Try this:
SELECT a.prodCode, a.description, a.unit, SUM(b.unitPrice)
FROM ProductTable a
LEFT JOIN PriceHistTable b ON a.prodCode = b.prodCode
GROUP BY a.prodCode, a.description, a.unit, b.unitPrice
Assuming you want to select unitPrice for prodCode with latest effDate, below query should work. Explanation in comments.
select x.prodCode, x.description, x.unit, y.unitPrice
from Product x
left join (
--- Create a table y with one row per (prodCode, effDate)
--- choosing the latest effDate per prodCode
select a.prodCode, a.effDate, a.unitPrice
from PriceHist a
join (
--- Create b as (prodCode, effDate)
select prodCode, max(effDate) as maxEffDate
from PriceHist
group by prodCode
) b
on a.prodCode = b.prodCode and a.effDate = b.maxEffDate
) y
on x.prodCode = y.prodCode

Find product id of the top selling product of each day, using total sold quantity to determine the top selling product

Adventureworks2008R2 database.
The result I want is each day the MaxQantity sold, for example, OrderDate 2007-09-01 shall have the max quantity of 96 only, but my query gives me 3 different results from the same day, maybe because it is considering the timestamp as well
SELECT DISTINCT CAST(oh.OrderDate AS DATE) OrderDate, (od.ProductID),SUM(od.OrderQty) MAXOrderQty
FROM Sales.SalesOrderDetail od
Inner Join Sales.SalesOrderHeader oh
ON od.SalesOrderID = oh.SalesOrderID
GROUP BY od.ProductID, CAST(oh.OrderDate AS DATE), od.OrderQty
ORDER BY SUM(od.OrderQty) DESC
You can write CTE and self JOIN on MAX Qty by date
;WITH CTE(OrderDate,ProductID,MAXOrderQty) AS(
SELECT CAST(oh.OrderDate AS DATE) OrderDate,od.ProductID,SUM(od.OrderQty) MAXOrderQty
FROM Sales.SalesOrderDetail od
Inner Join Sales.SalesOrderHeader oh
ON od.SalesOrderID = oh.SalesOrderID
GROUP BY od.ProductID, CAST(oh.OrderDate AS DATE)
)
SELECT t1.*
FROM CTE t1 INNER JOIN (
select OrderDate,MAX(MAXOrderQty) 'MAXOrderQty'
from CTE
GROUP BY OrderDate
)t2 on t1.OrderDate = t2.OrderDate and t1.MAXOrderQty = t2.MAXOrderQty
It's much easier addressing problems like this with window functions. In this case, rank should do the trick:
SELECT OrderDate, ProductID, MaxOrderQty
FROM (SELECT OrderDate, ProductID, MaxOrderQty,
RANK() OVER (PARTITION BY OrderDate ORDER BY MaxOrderQty DESC) AS rk
FROM Sales.SalesOrderDetail) s
WHERE rk = 1

Magento: How to query (SQL) top selling products?

Im seeking for a SQL query to directly get a list of our top selling products (ordered by quantity or by amount - doesn´t really matter). This seems to be more difficult than I thought...
Searching with google only finds solutions for PHP-modules and so on - but I want SQL.
I have picked up a small query from a different site and modified it a bit:
SELECT
SUM(order_items.qty_ordered) AS ordered_qty, order_items.name AS order_items_name, order_items.product_id AS entity_id,
e.entity_type_id, e.attribute_set_id, e.type_id, e.sku, e.has_options, e.required_options, e.created_at,
e.updated_at FROM sales_flat_order_item AS order_items
INNER JOIN sales_flat_order AS `order` ON `order`.entity_id = order_items.order_id AND `order`.state <> 'canceled'
LEFT JOIN catalog_product_entity AS e
ON
-- (e.type_id NOT IN ('grouped', 'configurable', 'bundle'))
-- AND
e.entity_id = order_items.product_id AND e.entity_type_id = 4
--AND state = "complete"
WHERE (parent_item_id IS NULL)
GROUP BY order_items.product_id
HAVING (SUM(order_items.qty_ordered) > 0)
ORDER BY ORDERED_QTY DESC
It more or less seems to give a reasonable output - but the numbers differ from the admin-start screen (where only the top 5 are displayed).
Has anybody done smth. similar to that already?
Have a solution (query) now
select
year_ordered,
product_type,
sku,
name,
sum(qty_ordered) as qty,
sum(row_total) as total
from (
SELECT
YEAR(so.created_at) AS year_ordered,
-- order_id,
product_type, sku, name, qty_ordered, price, row_total
FROM `sales_flat_order` AS so
INNER JOIN `sales_flat_order_item` AS si ON si.order_id=so.entity_id
AND (so.state != "canceled" )
ORDER BY so.created_at desc
) stat
group by stat.year_ordered, stat.product_type, stat.sku, stat.name
order by year_ordered desc, total desc
I´m using a subquery to be able to control that counting the products is correct.
SELECT
YEAR(so.created_at) AS year_ordered,
-- order_id,
product_type, sku, name, qty_ordered, price, row_total
FROM `sales_flat_order` AS so
INNER JOIN `sales_flat_order_item` AS si ON si.order_id=so.entity_id
AND (so.state != "canceled" )
ORDER BY so.created_at desc
Result is a list of the ordered products per year. If you want to see a best seller list over all years a slight modification is sufficient (here ordered by total).
select
product_type,
sku,
name,
sum(qty_ordered) as qty,
sum(row_total) as total
from (
SELECT
YEAR(so.created_at) AS year_ordered,
-- order_id,
product_type, sku, name, qty_ordered, price, row_total
FROM `sales_flat_order` AS so
INNER JOIN `sales_flat_order_item` AS si ON si.order_id=so.entity_id
AND (so.state != "canceled" )
ORDER BY so.created_at desc
) stat
group by stat.product_type, stat.sku, stat.name
order by total desc

Select Top1 from multiple-column query for each product ID

I have a query in SQLServer that returns the last entry in our stock of a given product, as well as many other columns. Something like:
SELECT
TOP(1) EntryDate,
EntryPrice,
TaxID,
TransportCost,
...
FROM
StockEntries
WHERE
ProductID = #ID
ORDER BY
EntryDate DESC
I cannot use MAX to get the last entry because sometimes it returns duplicate rows (when there are two entries at the same day).
I would like to execute this query for every product we have. I could do this if the query returned only 1 row, such as:
SELECT
ProductID p,
(
SELECT
TOP(1) s.EntryDate
FROM
StockEntries s
WHERE
s.ProductID = p.ProductID
ORDER BY
s.EntryDate DESC
)
FROM
Products p
But as it returns multiple rows, I cannot see a straight way to do this.
Any ideas?
As you have phrased the question, cross apply seems very appropriate:
SELECT p.*, s.*
FROM products p CROSS APPLY
(SELECT TOP(1) s.*
FROM StockEntries s
WHERE s.ProductID = p.ProductID
ORDER BY s.EntryDate DESC
) s;
APPLY also allows you to select other columns from StockEntries.
you can use ROW_NUMBER() to rank each row and then just get the rows with the highest entry date per product.
SELECT *
FROM (SELECT p.productid,
s.EntryDate,
s.EntryPrice,
s.TaxID,
s.TransportCost,
ROW_NUMBER() OVER (PARTITION BY p.productid ORDER BY s.entrydate DESC) rownum
FROM products p
JOIN StockEntries s ON s.ProductID = p.ProductID
) t
WHERE rownum = 1

List vendors, and lowest priced product SQL

I am trying to join 2 tables and create a new field returning the lowest value of a product. I've tried many variations and can't seem to get it to work.
SELECT DISTINCT VENDOR.*, PRODUCT.P_PRICE, PRODUCT.LOWEST_PRICE AS MIN(PRODUCT.P_PRICE)
FROM PRODUCT
INNER JOIN VENDOR
ON VENDOR.V_CODE = PRODUCT.V_CODE
ORDER BY VENDOR.V_NAME
You can use this, This will order from Minimum price vendor product
SELECT VENDOR.V_NAME, MIN(PRODUCT.P_PRICE) AS LOWEST_PRICE
FROM VENDOR
INNER JOIN PRODUCT
ON VENDOR.V_CODE = PRODUCT.V_CODE
GROUP BY VENDOR.V_NAME
ORDER BY LOWEST_PRICE
SQL FIDDLE:- http://sqlfiddle.com/#!3/467c8/2
If you are looking for the lowest price by vendor, use group by and min:
SELECT VENDOR.V_NAME, MIN(PRODUCT.P_PRICE) AS LOWEST_PRICE
FROM PRODUCT
INNER JOIN VENDOR
ON VENDOR.V_CODE = PRODUCT.V_CODE
GROUP BY VENDOR.V_NAME
ORDER BY VENDOR.V_NAME
Not knowing how your schema is defined try this:
SELECT
VENDOR.V_NAME,
PRODUCT.P_PRICE AS [VENDOR PRICE],
MIN(PRODUCT.P_PRICE) AS [LOWEST PRICE]
FROM
PRODUCT
INNER JOIN VENDOR ON VENDOR.V_CODE = PRODUCT.V_CODE
GROUP BY
VENDOR.V_NAME,PRODUCT.P_PRICE
ORDER BY
VENDOR.V_NAME
If you want the lowest price product per vendor, I would suggest using window functions:
select pv.*
from (select v.v_name, p.p_name, p.p_price
row_number() over (partition by p.v_code order by p.p_price asc) as seqnum
from vendor v join
product p
on v.v_code = p.v_code
) pv
where seqnum = 1