To Display a Stock Details - sql-server

I am trying to display the stock details like MRP, Sales Rate , Tax Amount and so on.
I used three grid views to make a entry in my form. They are,
GV Purchase
GV Product Details - (It is used to show the product name and product code )
GV Stock Details - (It is used to show the Quantity, MRP, Sales Price and so on)
I used SQL Query for populate the DB records in my grid view.
I select a Product A from Product Grid view in my form ,the Stock grid will show the corresponding data of the Product A
My DB records,
code Name QTY MRP S.Rate
aa11 Pro A 5 120.00 130.00
aa11 Pro A 2 130.00 150.00
aa12 Pro B 4 100.00 110.00
aa13 Pro C 2 50.00 60.00
When I select Pro A in GV Product Details in my form. The GV Stock Details will be shown the QTY, MRP, S.Rate for the Pro A
But My Query returns like this format
aa11 Pro A 5 120.00 130.00
2 130.00 150.00
4 100.00 110.00
2 50.00 60.00
This is my Query,
select s.*,iif( d.NewSalePrice is null,s.saleprice1,d.NewSalePrice)as NewSalePrice,Pdate from (select s.*,p.ProductFullName,p.ProductCode from Stock s,Product p where s.productfullcode=p.ProductFullCode) s left join(select Productfullcode,MRP,PUnitPrice,NewSalePrice,Pdate from DailyPricing ) d on s.ProductFullCode=d.ProductFullCode where s.MRP=d.MRP and s.UnitPrice=d.PUnitPrice and Pdate=(select MAX(Pdate) from DailyPricing where PUnitPrice=s.UnitPrice and mrp=s.MRP and ProductFullCode=s.ProductFullCode) order by ProductFullCode
How to I get Stock details only matched by Pro A
Note : These table format is just a model for my Table
Thanks in Advance,
Vinayak vk.:-)

You could probably simplify your query, and add a where clause for the product name you need.
Haven't tested it against mock data, but something like this SQL:
select
s.*,
p.ProductFullName,
p.ProductCode,
coalesce(d.NewSalePrice, s.saleprice1) as SalePrice,
max(d.Pdate) over (partition by p.ProductFullCode, s.mrp, s.UnitPrice) as MaxPdate
from Product p
join Stock s on s.productfullcode = p.ProductFullCode
join DailyPricing d on (s.ProductFullCode = d.ProductFullCode and s.MRP = d.MRP and s.UnitPrice = d.PUnitPrice)
where p.ProductFullName = 'Pro A'
order by p.ProductFullCode

Related

Show Quantity with Quantity Breakdown by Batch numbers

I have written a query in T-SQL that extracts StockNo, StockQty, CostPrice, BatchNo, BatchQty and StockValue. Something similar to a Stock Audit report. The BatchNo and BatchQty exists on TableB while the StockNo, StockQty, CostPrice and StockValue are from TableA. The BatchQty is the breakdown of the StockQty for Batched Items. So yes, the query returns the StockNo and it's relevant batch quantity if applicable. I am trying to write the query such that it shows the StockQty and next to that the BatchQty breakdown with duplicating or bringing in the StockValue again.
I am using SQL 2016.
I have tried different join types, temp tables as well as a union. I have also researched different SQL forums to see if there is a possible solution that I can use.
SELECT
TRANS_ID
STOCKNO,
BATCHMANAGED,
BATCHNO,
STOCKQTY,
BATCHQTY,
COSTPRICE,
STOCKVALUE,
FROM TABLE_A T0
FULL JOIN TABLE_B T1 ON T0.STOCKNO = T1.STOCKNO AND T0.TRANS_ID = T1_BASE_ID
I had to go with a full join as I needed Stock items that were both Batched and Non-Batched. Any other join I tried, omitted certain stock items and the total Stock Value didn't balance back to the Trial Balance.
Below is the result I currently get, which is extracting the StockQty and StockValue twice and in certain cases more than twice depending on the BatchNo and BatchQty:
StockNo BatchManaged BatchNo StockQty BatchQty CostPrice StockValue
Item1 Y BN0001 20 10 10.00 200
Item1 Y BN0002 20 10 10.00 200
Item2 Y BN0003 40 24 30.00 1200
Item2 Y BN0004 20 16 30.00 1200
Item3 N 50 20.00 1000
Total 3800
This is the output I am trying to achieve where the StockQty and StockValue is not shown for every batch number.They need to just show once:
StockNo BatchManaged BatchNo StockQty BatchQty CostPrice StockValue
Item1 Y BN0001 20 10 10.00 200
Item1 Y BN0002 10 10.00
Item2 Y BN0003 40 24 30.00 1200
Item2 Y BN0004 16 30.00
Item3 N 50 20 1000
Total 2400

Error on Group by method

I wrote a query to combine records in multiple tables. Tables named by Purchase Order, Purchase Order Item
[ Note: The column names are not original names, it just for a model data]
In purchase order table have the order details like this,
id date vendorid totalitems totalqty grossamnt netamnt taxamt
----------------------------------------------------------------------------
1 03/10/17 00001 2 6 12000 13000 1000
Purchase Order Item table have the order details like this,
poid id productcode qty rate tax(%) taxamnt total
--------------------------------------------------------
1 1 12001 3 6000 2.5 500 6500
2 1 12000 3 6000 2.5 500 6500
My Query is,
select po.POID,po.SupplierId,po.TotalItems from
PurchaseOrder po, PurchaseOrderItem poi where po.POID=poi.POID group by
po.POID, po.SupplierId,po.TotalItems
Query returns,
id vendorid totalitems
--------------------------
1 00001 2
1 00001 2
Expected Output is,
id vendorid totalitems
------------------------
1 00001 2
You are using an outdated join method, have a read here:
ANSI vs. non-ANSI SQL JOIN syntax
You are also joining to another table, but never use it:
select po.POID,po.SupplierId,po.TotalItems
from PurchaseOrder po, PurchaseOrderItem poi
where po.POID=poi.POID
group by po.POID, po.SupplierId,po.TotalItems
Can just be:
select po.POID,po.SupplierId,po.TotalItems
from PurchaseOrder po
group by po.POID, po.SupplierId,po.TotalItem
OR
select DISTINCT
po.POID,
po.SupplierId,
po.TotalItems
from PurchaseOrder po

SQL Server - Group by day for the top N of the range

What I need to do is get a Cost breakout for each grouping, aggregated by day. Also, only taking the top N per the whole date range. I'm probably not explaining this well so let me give examples. Say my table schema and data looks like this:
SoldDate Product State Cost
----------------------- --------------------- --------- ------
2017-07-11 01:00:00.000 Apple NY 6
2017-07-11 07:00:00.000 Banana NY 1
2017-07-11 07:00:00.000 Banana NY 1
2017-07-12 01:00:00.000 Pear NY 2
2017-07-12 03:00:00.000 Olive TX 1
2017-07-12 16:00:00.000 Banana NY 1
2017-07-13 22:00:00.000 Apple NY 6
2017-07-13 22:00:00.000 Apple NY 6
2017-07-13 23:00:00.000 Banana NY 1
Call this table SoldProduce.
Now what I'm looking for is to group by Day, Product and State but for each day, only take the top two of the group NOT the top of that particular day. Anything else gets lumped under 'other'.
So in this case, our top two groups with the greatest Cost are Apple-NY and Banana-NY. So those are the two that should show up in the output only. Anything else is under 'Other'
So in the end this is the desired output:
SoldDay Product State Total Cost
----------------------- --------------------- --------- ------
2017-07-11 00:00:00.000 Apple NY 6
2017-07-11 00:00:00.000 Banana NY 2
2017-07-11 00:00:00.000 OTHER OTHER 0
2017-07-12 00:00:00.000 OTHER OTHER 3
2017-07-12 00:00:00.000 Banana NY 1
2017-07-13 00:00:00.000 Apple NY 12
2017-07-13 00:00:00.000 Banana NY 1
2017-07-13 00:00:00.000 OTHER OTHER 0
Note how on the 12th Pear and Olive were lumped under other. Even though it outsold Banana on that day. This is because I want the Top N selling groups for the whole range, not just on a day by day basis.
I did a lot of googleing a way to make a query to get this data but I'm not sure if it's the best way:
WITH TopX AS
(
SELECT
b.Product,
b.State,
b.SoldDate,
b.Cost,
DENSE_RANK() OVER (ORDER BY GroupedCost DESC) as [Rank]
FROM
(
SELECT
b.Product,
b.State,
b.SoldDate,
b.Cost,
SUM(b.Cost) OVER (PARTITION BY b.Product, b.State) as GroupedCost
FROM
SoldProduce b WITH (NOLOCK)
) as b
)
SELECT
DATEADD(d,DATEDIFF(d,0,SoldDate),0),
b.Product,
b.State,
SUM(b.Cost)
FROM
TopX b
WHERE
[Rank] <= 2
GROUP BY
DATEADD(d,DATEDIFF(d,0,SoldDate),0),
b.Product,
b.State
UNION ALL
SELECT
DATEADD(d,DATEDIFF(d,0,SoldDate),0),
null,
null,
SUM(b.Cost)
from
TopX b
WHERE
[Rank] > 2
GROUP BY
DATEADD(d,DATEDIFF(d,0,SoldDate),0)
Step 1) Create a common query that first projects the cost that the row would be has we just grouped by Product and State. Then it does a second projection to rank that cost 1-N where 1 has the greatest grouped cost.
Step 2) Call upon the common query, grouping by day and restricting to rows <= 2. This is the Top elements. Then union the other category to this, or anything ranked > 2.
What do you guys think? Is this an efficient solution? Could I do this better?
Edit:
FuzzyTrees suggestion benchmarks better than mine.
Final query used:
WITH TopX AS
(
SELECT
TOP(2)
b.Product,
b.State
FROM
SoldProduce b
GROUP BY
b.Product,
b.State
ORDER BY
SUM(b.Cost)
)
SELECT
DATEADD(d,DATEDIFF(d,0,SoldDate),0),
coalesce(b.Product, 'Other') Product,
coalesce(b.State, 'Other') State,
SUM(b.Cost)
FROM
SoldProduce a
LEFT JOIN TopX b ON
(a.Product = b.Product OR (a.Product IS NULL AND b.Product IS NULL)) AND
(a.State = b.State OR (a.State IS NULL AND b.State IS NULL))
GROUP BY
DATEADD(d,DATEDIFF(d,0,SoldDate),0),
coalesce(b.Product, 'Other') Product,
coalesce(b.State, 'Other') State,
ORDER BY DATEADD(d,DATEDIFF(d,0,SoldDate),0)
-- Order by optional. Just for display purposes.
--More effienct to order in code for the final product.
--Don't use I/O if you don't have to :)
I suggest using a plain group by without window functions for your TopX view:
With TopX AS
(
select top 2 Product, State
from SoldProduce
group by Product, State
order by sum(cost) desc
)
Then you can left join to your TopX view and use coalesce to determine which products fall into the Other group
select
coalesce(TopX.Product, 'Other') Product,
coalesce(TopX.State, 'Other') State,
sum(Cost),
sp.SoldDate
from SoldProduce sp
left join TopX on TopX.Product = sp.Product
and TopX.State = sp.State
group by
coalesce(TopX.Product, 'Other'),
coalesce(TopX.State, 'Other'),
SoldDate
order by SoldDate
Note: This query will not return 0 counts

UPDATE SQL Query to update a table based on two dates

i would like to update my query table based on two dates, i tried the following code but it didn't work
UPDATE [Stock Report] INNER JOIN Report ON [Stock Report].ItemID = Report.ItemID SET [Stock Report].Amount = SUM(Report.Amount) WHERE [Date Product Was Made] BETWEEN #AA AND #BB
My two query tables are Report and Stock Report
Report Table
ItemID| Item |Date Product Was Made|Amount|ProductID|Product Name
10 Flour 11/17/2015 100 54 Saltbread
11 Bran Flakes 11/17/2015 100 54 Saltbread
10 Flour 11/17/2015 100 54 Saltbread
11 Bran Flakes 11/17/2015 100 54 Saltbread
What i would like to see in Stock Report Table
ItemID| Item | Start Date | End Date |Amount
10 Flour 11/16/2015 11/25/2015 200
11 Bran Flakes 11/16/2015 11/25/2015 200
The dates can be any two random dates but the table should generate a total based on the amount used in between the date ranges. Wht]at would be the SQL code to complete this process
As EuphoriaGrogi mentioned, you were pretty close.
SELECT ItemID, Item, #AA AS StartDate, #BB AS EndDate, SUM(Amount) AS TotalAmount
FROM (YourReportTableQueryWith#AAAnd#BBParametersHere) AS SubQuery
GROUP BY SubQuery.ItemID,SubQuery.Item
More on GROUP BY here: http://www.w3schools.com/sql/sql_groupby.asp
You tagged with mysql, sql-server and ms-access.
But answers will differ for each case.
Here SQLServer solution:
WITH SumAmount AS (
SELECT
ItemId
,SUM(Report.amount) as sum_amount
FROM
Report
GROUP BY
ItemId
)
UPDATE SR
SET
amount = SA.sum_amount
FROM
[Stock Report] SR
JOIN SumAmount SA ON SR.ItemID = SA.ItemID
WHERE
[Date Product Was Made] BETWEEN #AA AND #BB
Supposed MS Access query (I'm not proficient with MSACCESS, going by http://www.fmsinc.com/microsoftaccess/query/snytax/update-query.html):
UPDATE [Stock Report]
JOIN (
SELECT
ItemId
,SUM(Report.amount) as sum_amount
FROM
Report
GROUP BY
ItemId
) SA ON [Stock Report].ItemID = SA.ItemID
SET
[Stock Report].amount = SA.sum_amount
WHERE
[Date Product Was Made] BETWEEN #AA AND #BB

SQL query to calculate Throughput based "subtracting" two Select statements using Group By

I'm trying to formulate a SQL query to calculate the difference in the number of people "arriving" and "departing" grouped by City and Date.
TravelerID ArrivalDate DepartureDate City
1 2015-10-01 2015-10-03 New York
2 2015-10-02 2015-10-03 New York
3 2015-10-02 2015-10-04 Chicago
4 2015-10-01 2015-10-02 Chicago
I'm hoping to get a table that looks like
NumOfTravelers Date City
1 2015-10-01 New York
1 2015-10-02 New York
-2 2015-10-03 New York
1 2015-10-01 Chicago
0 2015-10-02 Chicago
-1 2015-10-04 Chicago
A positive number for NumOfTravelers means that more people arrived in that city on that particular date. A negative number for NumOfTravelers means that more people left that city on that particular date.
In trying to break down this SQL query, I've tried
SELECT COUNT(TravelerID) as NumTravelersArrivng, ArrivalDate, City FROM TravelTable GROUP BY ArrivalDate, City;
SELECT COUNT(TravelerID) as NumTravelersDeparting, DepartureDate, City FROM TravelTable GROUP BY DepartureDate, City;
I'm trying to get "NumTravelersArriving" - "NumTravelersDeparting" into a column that represents "traveler throughput" grouped by City and Date.
I've been so stumped on this. I'm using SQL Server, and having a frustrating time using Table aliases and Column aliases.
Try this:
SELECT *
FROM (
SELECT City, ArrivalDate As Date, COUNT(TravelerID) As NumOfTravelers
FROM TravelTable
GROUP BY City, ArrivalDate
) a
FULL JOIN (
SELECT City, DepartureDate As Date, COUNT(TravelerID) * -1 As NumOfTravelers
FROM TravelTable
GROUP BY City, DepartureDate
) b ON b.City = a.City AND b.Date = a.Date

Resources