Query to get output for stock - sql

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)

Related

SQL - create flag in query to highlight order which contain quantity = 1

I have tried creating a case statement but doesn't seem to give me what i want. Id like to get a split of the table (which is at a product level) and aggregate at an order level of items which contain quantity of 1.
Any ideas on how I would do this?
order id | Product | Quantity
---------+---------+--------------
11111 | sdsd4 | 1 (single item )
22222 | sasas | 1 (multiple items)
22222 | wertt | 1 (multiple items)
I'd like to get a case statement to add another column to split out orders with quantity = 1 and orders greater 1
Any idea on how I would do this?
The desired outcome would be the column in (brackets)
I could then count the orders and bring in the newly created column as the dimension
More detail here:
enter image description here
Attached is an image of table structure.
Logic, if quantity = 1 and 1 order then single item order
if order has one item but multiples of same item non single item order
if order has more than one product then non single item order
If your database supports analytic functions, then you can use a query like this one:
SELECT *,
CASE WHEN count("Product") OVER (partition by "order id") > 1
THEN 'multiple items' ELSE 'single item'
END As "How many items"
FROM Table1
Demo: https://dbfiddle.uk/?rdbms=postgres_11&fiddle=b659279fc16d2084cb1cf4a3bea361a1
Below is for BigQuery Standard SQL
#standardSQL
SELECT *,
CASE COUNT(DISTINCT Product) OVER(PARTITION BY order_id)
WHEN 1 THEN 'Single Item Order'
ELSE 'Multiple Items Order'
END Single_or_Multiple
FROM `project.dataset.table`
You can test, play with above using dummy data as below
#standardSQL
WITH `project.dataset.table` AS (
SELECT 11111 order_id, 'sdsd4' Product, 1 Quantity UNION ALL
SELECT 22222, 'sasas', 2 UNION ALL
SELECT 22222, 'wertt', 1
)
SELECT *,
CASE COUNT(DISTINCT Product) OVER(PARTITION BY order_id)
WHEN 1 THEN 'Single Item Order'
ELSE 'Multiple Items Order'
END Single_or_Multiple
FROM `project.dataset.table`
with result
Row order_id Product Quantity Single_or_Multiple
1 11111 sdsd4 1 Single Item Order
2 22222 sasas 2 Multiple Items Order
3 22222 wertt 1 Multiple Items Order
If I understand this right, you could use a subquery to get the count of records for an order and flag a record, if this count is larger then 1 and the quantity is equal to 1.
SELECT t1.order_id,
t1.product,
t1.quantity,
CASE
WHEN t1.quantity = 1
AND (SELECT count(*)
FROM elbat t2
WHERE t2.order_id = t1.order_id) > 1 THEN
'flag'
ELSE
'no flag'
END flag
FROM elbat t1;

Case in Sql group by query

I am working on a project in which I want to use Case to calculate price of product under specific Reference Number in SQL server. Below is my Sql query
SELECT
product AS Products,
refNum AS Refrence,
COUNT(id) AS Count
FROM ProductPriceList
GROUP BY
refNum, product
By Executing Above query I get:
Product Reference Count
Product1 Ref08 24
Product2 Ref08 7
Product3 Ref07 32
Product2 Ref12 1
Product3 Ref12 18
Product1 Ref07 76
Product1 Null 56
Can anyone guide me how to use Case statement in Sql query with group by statement to show price Below is the case:
if count < 10 then price 1
if count > 10 and < 100 then price 2
if count > 100 then price 3
I don't want to add a new table in my database. I hope you can understand my query.
Thanks in advance.
I think a basic CASE expression can handle your requirement:
SELECT
product AS Products,
refNum AS Refrence,
CASE WHEN COUNT(*) < 10 THEN 1
WHEN COUNT(*) >= 10 AND COUNT(*) < 100 THEN 2
ELSE 3 END AS price
FROM ProductPriceList
GROUP BY
product, refNum;
Not much to explain here, except that the 2 price case uses a bound which includes the count of 10 (since the 1 price case excludes it).
Here's alternative (doesn't differ much from exisiting one though):
You can use your query in subquery and use case outside:
select product,
--to get NULL values back
case Reference when 'RefNull' then NULL else Reference end [Reference],
case when [Count] < 10 then 1
when [Count] between 10 and 100 then 2
else 3 end [price]
from (
SELECT product AS Products,
--to allow also null values to be grouped
coalesce(refNum, 'RefNull') AS Refrence,
COUNT(id) AS Count
FROM ProductPriceList
GROUP BY coalesce(refNum, 'RefNull'), product
) [a]
Dataset:
Create Table ProductPriceList
(
Product varchar(10)
,RefNum CHAR(5)
,Records Int
);
Insert into ProductPriceList
Values
('Product1','Ref08',24)
,('Product2','Ref08',7)
,('Product3','Ref07',32)
,('Product2','Ref12',1)
,('Product3','Ref12',18)
,('Product1','Ref07',76)
,('Product1', NULL, 56);
With RCTE AS
(
Select Product
,RefNum
,Records
,1 RowNo
From ProductPriceList PPL
Union All
Select Product
,RefNum
,Records
,RowNo + 1
From RCTE R
Where RowNo + 1 < Records
)
Insert Into ProductPriceList (Product, RefNum, Records)
Select Product, RefNum, Records
From RCTE
where Records > 1
Query to fetch desired result:
Select Product
,RefNum
,Case When Count(*) < 10 Then 1
When Count(*) Between 10 and 99 then 2
Else 3 End Price
From ProductPriceList
Group By Product, RefNum
SQL Fiddle

How to display only few columns of a table based on the data

Consider the table below
Name partno. sch_date WO# owed panels
aa 1234 08/22/2017 121 22 26
aa 1234 08/22/2017 222 22 27
aa 1234 08/22/2017 242 22 27
aa 1234 08/29/2017 152 20 24
aa 1234 08/29/2017 167 20 24
aa 1234 08/29/2017 202 20 26`
Is it possible to display the data in such way that when the number of panels is greater than owed, then i don't won't to dispaly the other partno. schedule on the same date(sch_date).
Expected Result
Name partno. sch_date WO# owed panels
aa 1234 08/22/2017 121 22 26
aa 1234 08/29/2017 152 20 24
Cross apply may help here. (note you can see why I asked about order in my earlier comment as the ORDER of records in a table is not guaranteed! we need to know in what you want the records evaluated! Date isn't enough (unless it has a time compoent not displayed that is different!)
WORKING example on Rextester: http://rextester.com/CAUK18185
Many assumptions made:
When owned is > panels you don't need to see the record.
You want to see the the lowest WO# when owed is < panels and suppress all other records including ones where owed > panels.
If there are no records for a date, name and partno that have owed < panels, you want to see no records.
If these assumptions are incorrect, please provide a better sample set and expected results to test these types of situations and explain what you want to have happen.
SELECT Distinct B.*
FROM tblName Z
CROSS APPLY (SELECT TOP 1 A.*
FROM tblName A
WHERE A.owed < A.panels
and Z.Name = A.Name
and Z.[partno.] = a.[partno.]
and Z.sch_date = a.sch_date
ORDER by A.name, A.[partno.], A.sch_date, A.[wo#]) B
For each record in A run a query which returns the lowest wo# for a name, partno and sch_date when the owed < panels.
UPDATED:
I see in a comment you want to keep records if owed > panels... if it's encountered first.... but what if it's not encountered first?
http://rextester.com/NXS51018
--First we get all the records w/ a owed < panels per group and assign the earliest row (that having the lowest WO) a RN of 1. then we return that set.
cte as (
Select A.*, row_number() over (Partition by Name, [partno.], sch_date ORDER BY [WO#]) RN
from tblName A
where owed < panels)
Select * from cte where RN =1
UNION ALL
--We then union in the records where owed >=panels and their WO# < the wo# from the CTE.
SELECT Z.*, 0 as rn FROM tblName Z where owed >=panels
and exists (Select * from cte
where Z.name = CTE.name
and Z.[partno.] = cte.[partno.]
and Z.sch_date = cte.sch_date
and CTE.[WO#] > Z.[WO#]) --Now this line may not be needed, depending on if you want all or just some of the WO#'s when owed >=panels.
ORDER BY name, [partno.], Sch_date, [Wo#]
After last comment update:
cte as (
Select A.*, row_number() over (Partition by Name, [partno.], sch_date ORDER BY [WO#]) RN
from tblName A
where owed < panels),
cte2 as (Select * from cte where RN =1
UNION ALL
SELECT Z.*, 0 as rn FROM tblName Z where owed >=panels
and exists (Select * from cte
where Z.name = CTE.name
and Z.[partno.] = cte.[partno.]
and Z.sch_date = cte.sch_date
and CTE.[WO#] > Z.[WO#]))
Select * into SOQ#45619304 from CTE2; --This line creates the table based on the 2nd cte results.
Select * from SOQ#45619304;
You can try this -
SELECT Name, partno., sch_date, WO#, owed, panels
FROM YOUR_TABLE
WHERE panels < owed
UNION ALL
SELECT Name, partno., sch_date, MIN(WO#), owed, MIN(panels)
FROM YOUR_TABLE
WHERE panels > owed
GROUP BY Name, partno., sch_date, owed
ORDER BY Name

How to retrieve data from XML column in SQL

I have the following table layout:
OrderDetails:
ItemID (PK, int, not null)
ItemName (nvarchar(450), null)
OrderID (FK, int, not null)
Discounts (nvarchar(max), null)
The Discounts column is declared nvarchar(max) but the data is really XML - no idea why it wasn't declared as XML. I need to query the table to show the OrderID, ItemName, prorated discounts, all other discounts, and total of prorated + all other discounts. Here is an example of some records.
ItemID ItemName OrderID Discounts
8610 Item 1 4227 SEE XML 4227 BELOW
8615 Item 2 4227 <DocumentElement></DocumentElement> //no discounts for this row
8620 Item 3 9387 SEE XML 9387 BELOW
XML OrderId = 4227:
<DocumentElement>
<DiscountsTable>
<DiscountDisplayName>Bundle A</DiscountDisplayName>
<DiscountValue>6.00</DiscountValue>
</DiscountsTable>
<DiscountsTable>
<DiscountDisplayName>Bundle B</DiscountDisplayName>
<DiscountValue>25.00</DiscountValue>
</DiscountsTable>
</DocumentElement>
XML for OrderId = 9387:
<DocumentElement>
<DiscountsTable>
<DiscountDisplayName>Prorated Discount</DiscountDisplayName>
<DiscountValue>6.45</DiscountValue>
</DiscountsTable>
<DiscountsTable>
<DiscountDisplayName>Bundle A</DiscountDisplayName>
<DiscountValue>5.61</DiscountValue>
</DiscountsTable>
<DiscountsTable>
<DiscountDisplayName>Bundle B</DiscountDisplayName>
<DiscountValue>23.39</DiscountValue>
</DiscountsTable>
</DocumentElement>
So, What I need is a query that will return the ItemID, ItemName, aggregated prorated discounts, aggregated bundled discounts, and a total of the discounts added together (prorated + bundled = total discounts). For the 3 records above, the query result should look like this:
Item ID Item Name Prorated Discounts Other Discounts Total Discounts
8610 Item 1 0.00 31.00 31.00
8615 Item 2 0.00 0.00 0.00
8620 Item 3 6.45 29.00 35.45
I've tried using the value() method but I get an error stating it can not be used with nvarchar(max). How do I parse the XML column to pull aggregated values?
You need to convert the column to XML first to use SQLXML features. Something like this.
;with tbl as (
select ItemID, ItemName, OrderID,
convert(xml, Discounts) as Discounts
from OrderDetails
)
select ItemID, ItemName, OrderID,
t.v.value('DiscountDisplayName[1]','varchar(100)') DiscountDisplayName,
t.v.value('DiscountValue[1]','float') DiscountValue
from tbl cross apply Discounts.nodes('DocumentElement/DiscountsTable') t(v)
Elaborate a little
;with tbl as (
select ItemID, ItemName, OrderID,
convert(xml, Discounts) as Discounts
from OrderDetails
),
tbl1 as (
select ItemID, ItemName, OrderID,
t.v.value('(DiscountsTable[DiscountDisplayName="Prorated Discount"]/DiscountValue)[1]','float') Prorated, -- filter
t.v.value('(DiscountsTable[DiscountDisplayName="Bundle A"]/DiscountValue)[1]','float') BundleA,
t.v.value('(DiscountsTable[DiscountDisplayName="Bundle B"]/DiscountValue)[1]','float') BundleB
from tbl cross apply Discounts.nodes('DocumentElement') t(v) --do not go deeper
)
select ItemID, ItemName, OrderID, isnull(Prorated, 0) Prorated,
isnull(BundleA, 0) + isnull(BundleB, 0) Other,
isnull(Prorated, 0) + isnull(BundleA, 0) + isnull(BundleB, 0) Total
from tbl1
I would solve it as follows:
WITH Conv AS
(
SELECT ItemID,ItemName,OrderID,CONVERT(xml,Discounts) XmlVal
FROM Src
)
SELECT ItemID, ItemName, OrderID, Prorated, Other, Prorated+Other Total
FROM Conv
CROSS APPLY
(
SELECT SUM(CASE X.exist('DiscountDisplayName[text() = "Prorated Discount"]')
WHEN 1 THEN X.value('DiscountValue[1]', 'decimal(15,2)')
ELSE 0 END) Prorated,
SUM(CASE X.exist('DiscountDisplayName[text() = "Prorated Discount"]')
WHEN 0 THEN X.value('DiscountValue[1]', 'decimal(15,2)')
ELSE 0 END) Other
FROM XmlVal.nodes('/DocumentElement/DiscountsTable') T(X)
) T(Prorated, Other)
Results:
ItemID ItemName OrderID Prorated Other Total
----------- -------- ----------- ------------ -------- ---------
8610 Item 1 4227 0.00 31.00 31.00
8615 Item 2 4227 NULL NULL NULL
8620 Item 3 9387 6.45 29.00 35.45
You can add COALESCE or ISNULL to remove NULLs.

How to extract the balance qty

I hv a table like this:-
TABLE A
--------------------------------
Date | Serial | Qty
--------------------------------
20110101 ABC 1
20110102 ABC -1
20110105 ABC 1
20110106 ABC 1
20110108 ABC -1
I need to know what's the balance qty of ABC (based on FIFO) using SQL & the final output will look something like this:-
Date Serial Qty
20110106 ABC 1
Thanks.
You just want to pick out one record from the table? Like this?
SELECT * FROM your_table WHERE Date = '20110106' AND Serial = 'ABC'
I think you want something like
SELECT serial, max(date), 1 qty, sum( qty*size ) size
FROM tableA
GROUP BY serial
If you can have a negative final output, whatever database engine you're using should have something equivalent to Oracle's SIGN and ABS functions
SELECT serial, max(date), sign( sum( qty*size ) ) qty, abs( sum( qty*size ) ) size
FROM tableA
GROUP BY serial
Note that I'm guessing that you want the total remaining quantity as of the last day and that you get this by netting the positive quantities against the negative quantities for all the rows in the table for a particular SERIAL. I think this is close but I'm not sure how you're getting the DATE value
SELECT MAX(date) AS date, serial, ABS(SUM(qty * size)) AS size, SIGN(SUM(qty * size)) AS qty
FROM your_table
GROUP BY serial
something like this:
select Serial, sum(qty) as Total, Size from table_a group by Serial, Size
would give you:
TABLE A
Serial Total Size
ABC 0 23
ABC 0 22
ABC 1 24
you can, of course, add a where clause to restrict the query further:
select Serial, sum(qty) as Total, Size from table_a where Serial='ABC' and Size=24 group by Serial, Size
would give you information for Serial ABC with Size 24, only:
Serial Total Size
ABC 1 24
or you can filter out anything with Total of zero using a having clause:
select Serial, sum(qty) as Total, Size from table_a group by Serial, Size having sum(qty) <> 0
Serial Total Size
ABC 1 24