SQL JOIN giving doubled values - sql

EDIT ---
SQL FIDDLE sqlfiddle.com/#!18/f08bd/4
I couldn't load all the data into this as running out of limit on SQL FIDDLE but somehow the results are correct there with the little of sample data, but on my database it doubles somehow.
I am trying to display a total quantity of products, their weight and price.
The results come from 4 different tables.
When I do this without join then I get proper values but when I use Join then I get double values on all outputs.
Without join I can't achieve this as these results need to be all in one table.
I tried not using Join and just including those tables in 'FROM' but that thrown me errors about issues converting to numeric. I also tried Union but didn't work.
When using no join and not trying to display all the values, I get the desired output but with missing columns that I missed out on purpose to test this.
SELECT PriceListTest.Description, COUNT(ItemCode) AS Quantity,
SUM(Weight) AS 'Weight', Item.Pieces, PriceListTest.Price,
CAST(SUM( PriceListTest.Price * Weight) as
DECIMAL(10,2)) as 'Unit Price', CAST(SUM(PriceListTest.Price * Weight) as
DECIMAL(10,2))
AS 'Nett Amount'
FROM StockItems
INNER JOIN PriceListTest ON
StockItems.ItemCode = PriceListTest.Description
INNER JOIN Item ON StockItems.ItemCode = Item.ShortCode
WHERE Barcode IN (SELECT DISTINCT Barcode FROM StockOuttbl
WHERE ContainedID = 'isr5063' AND Status ='' GROUP BY Barcode) AND
PriceListTest.CustomerID = (SELECT DISTINCT CustomerID From Customerstbl
WHERE CustomerID ='1')
GROUP BY PriceListTest.Description, Item.Pieces, PriceListTest.Price;
Status in this case is empty, so that's not the issue
I getting these values:
Description Quantity Weight Pieces Price Unit Price Nett Amount
MAJ 52 20242 0 1.23 24897.66 24897.66
FLOCK 50 17206 0 1.23 21163.38 21163.38
This is the output I am looking:
Description Quantity Weight Pieces Price Unit Price Nett Amount
MAJ 26 10121 0 1.23 12448.83‬ 12448.83
‬
FLOCK 25 8603 0 1.23 10581.69 10581.69
When I don't use the PriceListTest in Join then I don't get the doubles, but then it's not exactly what I am looking for.
I get:
Description Quantity Weight Pieces
MAJ 26 10121 0
FLOCK 25 8603 0
EDIT-- Added the data for the tables
PriceListTest---
OID ShortCode Description CustomerID Price
7372 MAJ MAJ 1 1.23
7373 FLOCK FLOCK 1 1.23
StockItems---
TimeStamp DateStamp ItemCode Barcode ID Weight
104414357 20190701 MAJ 20190701104413935 7198 302
125350401 20190701 MAJ 20190701125349979 7220 360
125507063 20190703 MAJ 20190703125506641 7513 336
StockOutTbl---
ID AddedTimeStamp Quant Line UserID Weight Barcode Status Type StockoutTimeStamp StockoutUser TerminalStockOut TerminalAdded AddedDateStamp StockOutDateStamp ContainedID
41 115020205 NULL NULL NULL 336 20190703125506641 NULL 115020208 user 1 TC20 NULL 20190704 20190704 isr5063
Item Table ----
OID ShortCode ScreenCode Description AdminOid Kilos Pieces Inactive CategoryTitleStr BigBale
203 MAJ MAJ MAJ NULL 0 0 0 45 1
204 FLOCK FLOCK FLOCK NULL 0 0 0 45 1
Excuse me for the bad formatting.
I'd appreciate any help with this. Thanks in advance!

use subquery and distinct prcelist from 2nd table in subquery then use join
and there is no need GROUP BY Barcode insside your subquery cause you alredy used distinct
SELECT PriceListTest.Description, COUNT(ItemCode) AS Quantity,
SUM(Weight) AS 'Weight', Item.Pieces, PriceListTest.Price,
CAST(SUM( PriceListTest.Price * Weight) as
DECIMAL(10,2)) as 'Unit Price', CAST(SUM(PriceListTest.Price * Weight) as
DECIMAL(10,2))
AS 'Nett Amount'
FROM StockItems
INNER JOIN( select distinct * from PriceListTest) as PriceListTest ON
StockItems.ItemCode = PriceListTest.Description
INNER JOIN Item ON StockItems.ItemCode = Item.ShortCode
WHERE Barcode IN (SELECT DISTINCT Barcode FROM StockOuttbl
WHERE ContainedID = 'isr5063' AND Status ='' ) AND
PriceListTest.CustomerID = (SELECT DISTINCT CustomerID From Customerstbl
WHERE CustomerID ='1')
GROUP BY PriceListTest.Description, Item.Pieces, PriceListTest.Price;

Related

SQL Server : percentage calculation with new records as output

I have the below table as an output of a SQL query
ID Car Type Units Sold
---------------------------
1 Sedan 250
2 SUV 125
3 Total 375
I want a SQL query / procedure to produce below output
ID Car Type Units Sold
--------------------------
1 Sedan 250
2 SUV 125
3 Total 375
4 Sedan_Pct 66.67 (250/375)
5 SUV_Pct 33.33 (125/375)
Please note that Car Type will be increased in future and I want the percentage of each car type which should be appended to current table as '_Pct'.
Typically we might expect to see the percentages as a separate column, not as separate rows. That being said, we can generate the output you want using grouping sets in SQL Server:
WITH cte AS (
SELECT ID, CarType, SUM (UnitsSold) AS UnitsSold
FROM yourTable
GROUP BY
GROUPING SETS((ID, CarType), (CarType), ())
)
SELECT
ID,
COALECSE(CarType, 'Total') AS CarType,
CASE WHEN ID IS NOT NULL OR CarType IS NULL
THEN UnitsSold
ELSE 100.0 * UnitsSold /
SUM(CASE WHEN ID IS NOT NULL THEN UnitsSold END) OVER () END AS PctUnitsSold
FROM cte
ORDER BY
ID DESC,
CASE WHEN CarType IS NULL THEN 0 ELSE 0 END,
CarType;
Demo
A simpler solution will be using Union
SELECT CarType, UnitSold FROM Car
UNION
SELECT 'Total' CarType, SUM(UnitSold) UnitSold FROM Car
UNION
SELECT CarType + '_Pct' AS CarType, UnitSold / (SELECT SUM(UnitSold) FROM Car) * 100 AS UnitSold FROM Car
Might not be ideal in the long run
query for mysql server
use union all in view or stored procedure -
declare #totalunitsold numeric(15,0);
set #totalunitsold = (select unitsold from car where cartype='total')
select cartype,unitsold from car
union all
select cartype + '_pct', (unitsold/#totalunitsold) as pct from car
this may help you
SELECT CarType+'_Pct', UnitSold/TotalSale*100
FROM Car cross join (select sum(UnitSold) TotalSale from Car) X
you can union that with your Table
Don't do it! Just add an additional column, not new rows:
select t.*,
t.units_sold * 100.0 / sum(case when t.car_type = 'Total' then units_sold end) over () as ratio
from (<your query here>) t;
One fundamental reason why you want a different column is because ratio has a different type from units_sold. Everything in a column (even in a result set) should be a similar attribute.

Query to get output for stock

I need output through query as per given below points
there is stock table contains all items with multiple salemrp
I need those records whose stock is present in multiple salemrp, but if there is only one salemrp for an item, I require also those records.
My query is as follows, please help me, how to manipulate this query.
SELECT
itemid,
grpid,
(SELECT
itemname
FROM sap_itemmASter
WHERE itemid=sap_stockmASter.itemid )AS itemname,
(SELECT grpname
FROM sap_grpmASter
WHERE grpid=sap_stockmASter.grpid) AS grpname,
(SELECT partno
FROM sap_itemmASter
WHERE itemid=sap_stockmASter.itemid) AS partno,
salemrp,
(SELECT brANDname
FROM sap_brANDmASter
WHERE brANDid IN (SELECT brANDid
FROM sap_itemmASter
WHERE itemid=sap_stockmASter.itemid)) AS catname,
(laneno + ' - ' + rackno) AS locno,
isnull(SUM(stkqty),0) AS balqty,
(SELECT top 1 (laneno + ' - ' + rackno)
FROM sap_stockloc
WHERE itemid=sap_stockmASter.itemid) AS storeloc
FROM sap_stockmASter
WHERE laneno!=''
AND itemid>0
AND grpid IN (SELECT grpid
FROM sap_grpmASter
WHERE isactive=1
AND isdel=1)
AND itemid IN (SELECT itemid
FROM sap_itemmASter
WHERE isdel=1
AND isactive=1
AND laneno=sap_stockmASter.laneno
AND rackno=sap_stockmASter.rackno)
AND grpid=37
GROUP BY itemid,grpid,laneno,rackno,salemrp
ORDER BY itemname
More information:
Item Name SaleMrp Qty
ABC 158.00 48
ABC 165.00 -11
ABC 170.00 5
In this I want to not display negative stock, but
XYZ 125.00 0
(I need this record as well, beacause it has only one mrp)
PQR 100.00 -5
(I need this record as well, beacause it has only one mrp)

SQL select statement similar to vertical search approximate match in Excel

Having a table with columns 'price' and 'quantity'.
e.g:
rec price qty
1. 10,00 1
2. 7,50 5
3. 5,00 25
4. 3,00 100
I need to select the price for a quantity of 65. This is the price of record 3. Qty 65 is between qty 25 and 100. How to solve this in a sql query?
You can solve that with an inner SQL statement which tries to find the highest quantity lower than or equal to your requested quantity of 65:
select pce.price
from prices pce
join ( select max(qty) qty
from prices
where qty <= 65
) pce2
on pce.qty = pce2.qty
Here pce2 is the join to match the prices line. The pce table is joined to have access to all fields joined. This will only work correctly if there are no duplicates in prices for qty.

mysql group by date with multiple join

SELECT
tba.UpdatedDate AS UpdatedDate,
tsh.SupplierID,
ts.ProductCode as ProductCode,
sum(tba.AfterDiscount) as AfterDiscount,
sum(tba.Quantity) as Quantity
FROM
tblstockhistory as tsh
left join tblstock as ts
on tsh.StockID=ts.StockID
left join tblbasket as tba
on ts.ProductCode=tba.ProductCode
and tsh.SupplierID=49
AND tba.Status=3
group by
tba.UpdatedDate
ORDER BY
Quantity DESC
i have the supplier table, the supplier id tagged in to tblstockhistory table, and in this tblstockhistory table contains the StockID(reference from tblstock table), and i have Stock table contains StockID, ProductCode ,
And i have the tblbasket table , in this am maintaining the ProductCode,
My idea here ,
i want to show thw stats by supplierID, when i pass the supplier id, it show show , this supplier supplied goods sale stats,
But the above query sometime return null value, and it takes too much time for excution, around 50 seconds ,
I what somthing like below from above query
Date SupplierID, Amount, Quantity
2010-12-12 12 12200 20
2010-12-12 40 10252 30
2010-12-12 10 12551 50
2010-12-13 22 1900 20
2010-12-13 40 18652 30
2010-12-13 85 19681 50
2010-12-15 22 1900 20
2010-12-15 40 18652 30
2010-12-15 85 19681 50
Does a tblstockhistory ever exist without a stockID. If it doesn't you can convert it to an inner join which can help.
e.g.
tblstockhistory as tsh
INNER join tblstock as ts
on tsh.StockID=ts.StockID
Also you might to consider adding indexes if they don't currently exist.
At the very least I would have the following fields indexed since they will likely be joined and queried commonly.
tblstockhistory.SockID
tblstockhistory.SupplierID
tblstock.StockID
tblstock.ProductCode
tblbasket.ProductCode
tblBacket.Status
tblbasket.UpdatedDate
Finally if its really important that this query be lightening fast you can create summary tables and update them periodically.
re write the group by clause as and try again
group by
tba.UpdatedDate, tsh.SupplierID
you have mentioned ProductCode in your query but not in the 'result' you wanted if you want to display ProductCode as well then add it to the group by clause or else remove it from the select clause.

Optimizing Query With Subselect

I'm trying to generate a sales reports which lists each product + total sales in a given month. Its a little tricky because the prices of products can change throughout the month. For example:
Between Jan-01 and Jan-15, my company sells 50 Widgets at a cost of $10 each
Between Jan-15 and Jan-31, my company sells 50 more Widgets at a cost of $15 each
The total sales of Widgets for January = (50 * 10) + (50 * 15) = $1250
This setup is represented in the database as follows:
Sales table
Sale_ID ProductID Sale_Date
1 1 2009-01-01
2 1 2009-01-01
3 1 2009-01-02
...
50 1 2009-01-15
51 1 2009-01-16
52 1 2009-01-17
...
100 1 2009-01-31
Prices table
Product_ID Sale_Date Price
1 2009-01-01 10.00
1 2009-01-16 15.00
When a price is defined in the prices table, it is applied to all products sold with the given ProductID from the given SaleDate going forward.
Basically, I'm looking for a query which returns data as follows:
Desired output
Sale_ID ProductID Sale_Date Price
1 1 2009-01-01 10.00
2 1 2009-01-01 10.00
3 1 2009-01-02 10.00
...
50 1 2009-01-15 10.00
51 1 2009-01-16 15.00
52 1 2009-01-17 15.00
...
100 1 2009-01-31 15.00
I have the following query:
SELECT
Sale_ID,
Product_ID,
Sale_Date,
(
SELECT TOP 1 Price
FROM Prices
WHERE
Prices.Product_ID = Sales.Product_ID
AND Prices.Sale_Date < Sales.Sale_Date
ORDER BY Prices.Sale_Date DESC
) as Price
FROM Sales
This works, but is there a more efficient query than a nested sub-select?
And before you point out that it would just be easier to include "price" in the Sales table, I should mention that the schema is maintained by another vendor and I'm unable to change it. And in case it matters, I'm using SQL Server 2000.
If you start storing start and end dates, or create a view that includes the start and end dates (you can even create an indexed view) then you can heavily simplify your query. (provided you are certain there are no range overlaps)
SELECT
Sale_ID,
Product_ID,
Sale_Date,
Price
FROM Sales
JOIN Prices on Sale_date > StartDate and Sale_Date <= EndDate
-- careful not to use between it includes both ends
Note:
A technique along these lines will allow you to do this with a view. Note, if you need to index the view, it will have to be juggled around quite a bit ..
create table t (d datetime)
insert t values(getdate())
insert t values(getdate()+1)
insert t values(getdate()+2)
go
create view myview
as
select start = isnull(max(t2.d), '1975-1-1'), finish = t1.d from t t1
left join t t2 on t1.d > t2.d
group by t1.d
select * from myview
start finish
----------------------- -----------------------
1975-01-01 00:00:00.000 2009-01-27 11:12:57.383
2009-01-27 11:12:57.383 2009-01-28 11:12:57.383
2009-01-28 11:12:57.383 2009-01-29 11:12:57.383
It's well to avoid these types of correlated subqueries. Here's a classic technique for such cases.
SELECT
Sale_ID,
Product_ID,
Sale_Date,
p1.Price
FROM Sales AS s
LEFT JOIN Prices AS p1 ON s.ProductID = p1.ProductID
AND s.Sale_Date >= p1.Sale_Date
LEFT JOIN Prices AS p2 ON s.ProductID = p2.ProductID
AND s.Sale_Date >= p2.Sale_Date
AND p2.Sale_Date > p1.Sale_Date
WHERE p2.Price IS NULL -- want this one not to be found
Use a left outer join on the pricing table as p2, and look for a NULL record demonstrating that the matched product-price record found in p1 is the most recent on or before the sales date.
(I would have inner-joined the first price match, but if there is none, it's nice to have the product show up anyway so you know there's a problem.)
Are you actually running into performance problems or are you just anticipating them? I would implement this exactly as you have, were my hands tied from a schema-modification standpoint as yours are.
I agreee with Sean. The code you have written is very clean and understandable. If you are having performance issues, then take the extra effort to make the code faster. Otherwise, you are making the code more complex for no reason. Nested sub-selects are extremely useful when used judiciously.
The combination of Product_ID and Sale_Date is your foreign key. Try a select-join on Product_ID, Sale_Date.