Item with quantity and price are queried from SQL server for Excel and Crystal Report. The quantity and price are bulk quantity (pounds). I need to convert it to bag quantity and bag price. Pounds per bag data is not in SQL server and it is different on each item. My item is around 20 only. I cannot create permanent or temporary table to store pounds per bag data in SQL Server. I can use CASE in SQL to calculate bag quantity and price. But, it needs two CASEs. How can I use one CASE or other method which can simplify the SQL and keep it simple to maintain? My current SQL.
SELECT Item, Quantity, Price,
CASE item
WHEN ‘Item1’ THEN Quantity/32
WHEN ‘Item2’ THEN Quantity/33
…
ELSE Quantity
END AS QtyPerBag,
CASE item
WHEN ‘Item1’ THEN Price*32
WHEN ‘Item2’ THEN Quantity*33
…
ELSE Price
END AS PricePerBag
FROM MasterTable
DhruvJoshi's approach is a good approach. Using the VALUES() constructor, it is even simpler:
SELECT mt.Item, mt.Quantity, mt.Price,
mt.Quantity/factors.Factor AS QtyPerBag,
Price * Factors.factor AS PricePerBag
FROM MasterTable mt LEFT JOIN
(VALUES ('Item1', 32), ('Item2', 33)
) factors(item, factor)
ON factors.item = mt.item;
Note: If you quantity is stored as an integer, then you should use decimal points for the factors (unless you want integer division).
As already pointed out in comments you should consider using table/set approach.
One way if you want to do that inside of a query is like below:
SELECT Item, Quantity, Price, Quantity/Factor AS QtyPerBag,
Price * Factor AS PricePerBag
FROM MasterTable LEFT JOIN
(
SELECT 'Item1' as Item, '32' as Factor
UNION
SELECT 'Item2' as Item, '33' as Factor
-- and so on ...
) T
ON T.item=masterTable.item
Related
I have a table that looks like this -
Table screenshot link - https://i.stack.imgur.com/Pztpq.png
I want to add a new column 'Manufacturer_Updated', such that -
If any particular 'Product' has more than 1 (distinct) 'Manufacturer', then the Manufacturer having highest 'Sales' should be populated in the 'Manufacturer_Updated' column for all rows of that particular 'Product'.
Ex - In the above screenshot, Product - 'TOTAL HAIR CARE NA' has 2 different Manufacturer, so in the 'Manufacturer_Updated' column, 'SEXY HAIR CONCEPTS' should appear for both the rows, as it has the higher sales.
Could someone pls help with this query? Thanks in Advance!
Something like this should work:
SELECT Manufacturer, Product, Sales, Manufacturer as Manufacturer_Updated FROM
WHERE amt_of_manufacturers > 1
((SELECT Product, max(Sales) as Sales, count(distinct Manufacturer) as amt_of_manufacturers
FROM your_table
GROUP BY Product) as q1
left join
(SELECT Manufacturer, Sales, Product
FROM your_table
) as q2
ON q1.Sales = q2.Sales
AND q1.Product = q2.Product
) as q3
In the first query (q1), you're retrieving maximum sales per each product along with amount of manufacturers for a specific product (used later in upper query). In the second one (q2) you just need to retrieve Manufacturer (to transform it later to Manufacturer_Updated), Sales and Product (as join keys). After this you only need to filter out all products with single manufacturer.
Alternatively, if you want to keep those, you can remove where amt_of_manufacturers > 1 and replace Manufacturer_Updated in the upper query with the following:
CASE WHEN
amt_of_manufacturers <=1 THEN null
ELSE Manufacturer
END AS Manufacturer_Updated
For a project I'm working on, I need to be able to communicate the quantity available to 'make' for a BOM item based on its contents. I won't go in-depth as to how this will be communicated, the base is in the SQL query.
The idea is fairly simple;
a BOM (Bill Of Material, indicating that it requires to be created) item (let's call this BOM1) has 1 or more stockitems linked to it. Having a quantity of 1 or higher. In this example let's take ITEM1 (3 units) ITEM2 (2 units) and ITEM3(5 units). Naturally, all of this is stored in a single table for referencing;
Secondary to that, there's the quantity in stock for each part within that BOM. this is stored in a 'bin content' table, example as below;
The sum of the stock, per item, is then summarised as below;
Now, based on the 'contribution' of each item to the BOM item, you can calculate the maximum available number to create;
in this scenario, based on ITEM3, I can create a maximum of 8 of item BOM1 as this has the lowest contribution (for lack of a better word I guess). Let's assume that parts can only be used once for a BOM item.
I can create a query for a single BOM item using a TOP 1 and ORDER BY ASC statement, the problem is that I have multiple BOM items, each having its own parts with multiple bin locations;
select TOP 1
BOM_ITEM.ITEM_NO
, (SUM(BIN_CONTENT.QTY) / BOM_ITEM.PART_ITEM_QTY) as AVAIL_TO_MAKE
from BOM_ITEM
JOIN BIN_CONTENT
ON BOM_ITEM.PART_ITEM_NO = BIN_CONTENT.ITEM_NO
WHERE BOM_ITEM.ITEM_NO = 'BOM1'
GROUP BY
BOM_ITEM.ITEM_NO
ORDER BY AVAIL_TO_MAKE ASC
So, based on the BOM item, I want to retrieve only the part item qty with the lowest 'contribution' so to communicate the theoretically available quantity to make, I just can't figure it out though.
any suggestions would be greatly appreciated!
The below query computes for each BOM item, how many items can be created given the available stock.
The query uses subquery to compute the stock across all bins. The main query groups by BOM item. For each BOM item, the minimum available to make is used. Additionally, the floor function is used to round down to an integer value.
WITH STOCK
USING (
SELECT ITEM_NO, SUM(QTY) AS QTY
FROM BIN_CONTENT
GROUP BY ITEM_NO
)
SELECT BOM_ITEM.ITEM_NO AS BOM_ITEM_NO,
FLOOR(MIN(STOCK.QTY / BOM_ITEM.PART_ITEM_QTY)) AS AVAIL_TO_MAKE
FROM BOM_ITEM
JOIN STOCK ON STOCK.ITEM_NO = BOM_ITEM.ITEM_NO
GROUP BY BOM_ITEM.ITEM_NO
I have a question about SQL, and I honestly tried to search methods before asking. I will give an abstract (but precise) description below, and will greatly appreciate your example of solution (SQL query).
What I have:
Table A with category ids of the items and prices (in USD) for each item. category id has int type of value, price is string and looks like "USD 200000000" (real value is multiplied by 10^7). Tables also has a kind column with int type of value.
Table B with relation of category id and name.
What I need:
Get a table with price diapasons (like 0-100 | 100-200 | ...) as column names and count amount of items for each category id (as lines names) in all of the price diapasons. All results must be filtered by kind parameter (from table A) with value 3.
Questions, that I encountered (and which caused to ask for an example of SQL query):
Cut "USD from price string value, divide it by 10^7 and convert to float.
Gather diapasons of price values (0-100 | 100-200 | ...), with given step in the given interval (max price is considered as unknown at the start). Example: step 100 on 0-500 interval, and step 200 for values >500.
Put diapasons of price values into column names of the result table.
For each diapason, count amount of items in each category (category_id). Left limit of diapason shall not be considered (e.g. on 1000-1200 diapason, items with price 1000 shall not be considered).
Using B table, display name instead of category id.
Response is appreciated, ignorance will be understood.
If you only need category ids, then you do not need B. What you are looking for is conditional aggregation, something like:
select category_id,
sum(case when cast(substring(price, 4, 100) as int)/10000000 < 100 then 1 else 0 end) as price_000_100
sum(case when cast(substring(price, 4, 100) as int)/10000000 >= 100 and cast(substring(price, 4, 100) as int)/10000000 < 200
then 1 else 0
end) as price_100_200,
. . .
from a
group by category_id
There is no standard way to do what you describe.
That is because to do (3) you need a pivot aka crosstab, and this is not in ANSI SQL. Each DBMS has it's own implementation. Plus dynamic columns in a pivot table are an additional complication.
For example, Postgres calls it a "crosstab" and requires the tablefunc module to be installed. See this SO question and the documentation. Compare to SQL Server, which uses the PIVOT command.
You can get close using reasonably standard SQL.
Here is an example based on SQLite. A little bit of conversion would provide a solution for other systems, e.g. SUBSTR would be substring(string [from int] [for int]) in postgre.
Assuming a data table of format:
and a category name table of:
then the following code will produce:
WITH dataCTE AS
(SELECT product_id AS 'ID', CAST(SUBSTR(price, 5) AS INT)/1000000 AS 'USD',
CASE WHEN (CAST(SUBSTR(price, 5) AS INT)/1000000) <= 500 THEN
100 ELSE 200
END AS 'Interval'
FROM data
WHERE kind = 3),
groupCTE AS
(SELECT dataCTE.ID AS 'ID', dataCTE.USD AS 'USD', dataCTE.Interval AS 'Interval',
CASE WHEN dataCTE.Interval = 100 THEN
CAST(dataCTE.USD AS INT)/100
ELSE
(CAST(dataCTE.USD-500 AS INT)/200)+5
END AS 'GroupID'
FROM dataCTE),
cleanCTE AS
(SELECT *, CASE WHEN groupCTE.Interval = 100 THEN
CAST(groupCTE.GroupID *100 AS VARCHAR)
|| '-' ||
CAST((groupCTE.GroupID *100)+99 AS VARCHAR)
ELSE
CAST(((groupCTE.GroupID-5)*200)+500 AS VARCHAR)
|| '-' ||
CAST(((groupCTE.GroupID-5)*200)+500+199 AS VARCHAR)
END AS 'diapason'
FROM groupCTE
INNER JOIN cat_name AS cn ON groupCTE.ID = cn.cat_id)
SELECT *
FROM cleanCTE;
If you modify the last SELECT to:
SELECT name, diapason, COUNT(diapason)
FROM cleanCTE
GROUP BY name, diapason;
then you get a grouped output:
This is as close as you will get without specifying the exact system; even then you will have a problem with dynamically creating the column names.
A newbie here. So please be kind :-)
I have 2 Tables namely Item & Item Entries.
Relation is: Item.No = ItemEntries.No.
In Item Entries Table I have Columns as Qty, Entry type, Purchase Amount, Sales Amount
I like to have a report which shows as below,
Item No. | Opening Quantity | Purchase Amount | Sales Amount
To calculate Opening Inventory I summed up the quantity field and the result is as expected. No problem in that. Now From that dataset I like to run a sub query which Calculates/Sum the Purchase amount for an Item that is a part of first dataset and similarly for Sales Amount.
Select(Item No.,Sum(IE.Quantity) As Quantity, Select(......Purchase Amount),Select(....Sales Amount)
I hope I was able to clear my doubts to you guys.
Something like :
SELECT ItemNo, sum(quantity), purchaseAmount, SalesAmount FROM Item i INNER JOIN ItemEntities ie on i.no = ie.no GROUP BY ItemNo, PurchaseAmount, SalesAmount;
I believe (if I understand what you want) that this is the solution to your problem
Select Item.No ,
Sum(IE.Quantity) As Quantity,
(Select(......Purchase Amount)) As ColumnName1 ,
(Select(....Sales Amount)) As ColumnName2
From your need to "sum the purchase amount for an item that is part of the first dataset and similarly for Sales Amount" I think what you're trying to achieve is one row for each item on the Item table with a sum for each of the Qty, Sales Amount and Purchase Amount. If so, then you can simply use a 'group by' clause which groups results together which have matching values for the columns specified.
SELECT I.no, SUM(IE.qty), SUM(IE.purchase_amount), SUM(IE.sales_amount)
FROM item I JOIN item_entries IE
ON I.no = IE.no
GROUP BY I.no;
See the group_by_clause for more details and some examples.
N.B. The join from the item tables isn't strictly required in this example, but if you're producing a report I suspect you might want to get things like a description - in which case you'll need to add those columns to the group by clause too.
You might need the sum of three columns from
ItemEntries table(Qty,PurchaseAmount,SalesAmount) for each Item.No
Select A.No,
Sum(B.Qty),
Sum(B.Purchaseamount),
Sum(B.Salesamount)
From Item A,
Itementries B
Where A.No = B.No
Group By A.No;
I have a column which stores data like this:
Product:
product1,product2,product5
product5,product7
product1
What I would like to do is count the number of occurrences there are of product1, product2, etc. but where the record contains multiple products I want it to double count them.
So for the above example the totals would be:
product1: 2
product2: 1
product5: 2
product7: 1
How can I achieve this?
I was trying something like this:
select count(case when prodcolumn like '%product1%' then 'product1' end) from myTable
This gets me the count for product1 appears but how do I extend this to go through each product?
I also tried something like this:
select new_productvalue, count(new_productvalue) from OpportunityExtensionBase
group by new_ProductValue
But that lists all different combinations of the products which were found and how many times they were found...
These products don't change so hard coding it is ok...
EDIT: here is what worked for me.
WITH Product_CTE (prod) AS
(SELECT
n.q.value('.', 'varchar(50)')
FROM (SELECT cast('<r>'+replace(new_productvalue, ';', '</r><r>')+'</r>' AS xml) FROM table) AS s(XMLCol)
CROSS APPLY s.XMLCol.nodes('r') AS n(q)
WHERE n.q.value('.', 'varchar(50)') <> '')
SELECT prod, count(*) AS [Num of Opps.] FROM Product_CTE GROUP BY prod
You have a lousy, lousy data structure, but sometimes one must make do with that. You should have a separate table storing each pair product/whatever pair -- that is the relational way.
with prodref as (
select 'product1' as prod union all
select 'product2' as prod union all
select 'product5' as prod union all
select 'product7' as prod
)
select p.prod, count(*)
from prodref pr left outer join
product p
on ','+p.col+',' like '%,'+pr.prod+',%'
group by p.prod;
This will be quite slow on a large table. And, the query cannot make use of standard indexes. But, it should work. If you can restructure the data, then you should.
Nevermind all you need if one split function
SQL query to split column data into rows
hope after this you can manage .