I am trying to get two new columns (stock type in this case) and their respective quantities. I have tried to use PIVOT but it seems rather limited in SQL.
Tried to use PIVOT
This is part of a larger query but this is the piece I would like to have return as two columns - one for stock type 'A' and one for ' ' - blank. As it is now this returns two rows - one for each stock type.
SELECT MATERIAL,
CASE
WHEN STOCK_TYPE = 'A'
THEN 'UNCOVERED QTY'
ELSE 'BLANK QTY'
END AS [STOCK TYPE],
SUM(QUANTITY) AS 'QUANITTY'
FROM VW_MRP_ALLOCATION
WHERE STOCK_TYPE IN ('A','')
AND MATERIAL = '011040'
GROUP BY STOCK_TYPE,
MATERIAL
This returns:
MATERIAL STOCK TYPE QUANITTY
------------------ ------------- ---------------------------------------
011040 BLANK QTY 67
011040 UNCOVERED QTY 1301
(2 rows affected)
I would like to return one row for the material with two columns - one for 'Uncovered Quantity' and one for ' Blank Quantity'.
Just use conditional aggregation:
SELECT MATERIAL,
SUM(CASE WHEN STOCK_TYPE = 'A' THEN QUANTITY END) as uncovered_qty,
SUM(CASE WHEN STOCK_TYPE <> 'A' THEN QUANTITY END) as blank_qty
FROM VW_MRP_ALLOCATION
WHERE STOCK_TYPE IN ('A', '') AND MATERIAL = '011040'
GROUP BY MATERIAL;
Related
I have 1 table (I can not modify it before) from a bulk insert, and I need to transpose all the rows in "VALUES" column into single columns. Except for the "YEAR" (going from 0 to 50) and the "VALUES" columns, the other 3 columns are filled with a unique value (example: in year 0 size is 'L', color is 'red' and price is '10' and this size,color and price values are constant for all my 50 years).
The input table is like this:
I would like to have as output all the "VALUES" in columns called for example "VALUE_0" "VALUE_1" "VALUE_2" "VALUE_3" etc, where the numbers 0,1,2,3 stand for the year considered.
CREATE TABLE #CURVE(
YEAR INT,
SIZE VARCHAR(100),
COLOR VARCHAR(100),
PRICE VARCHAR(100),
VALUES FLOAT
)
The Output should be:
One option uses conditional aggregation:
select
size,
color,
price,
max(case when year = 0 then value end) value_0,
max(case when year = 1 then value end) value_1,
max(case when year = 2 then value end) value_2,
max(case when year = 3 then value end) value_3,
max(case when year = 4 then value end) value_4,
max(case when year = 5 then value end) value_5
from #curve
group by size, color, price
You can easily extend the select clause to handle more years.
This is a cross-database solution, that usually performs as good or better than vendor-specific implementations of pivot. On top of that (and for what it's worth), I find it easier to understand.
we need to know how many values do you expect in Values column for a year?
Otherwise the query looks like this:
SELECT [YEAR], [SIZE], [COLOR], [PRICE], [1] as [Value1], [2] as [Value2], [3] as [Value3]
FROM (
SELECT *, ROW_NUMBER() OVER(PARTITION BY [YEAR], [SIZE], [COLOR], [PRICE] ORDER BY (SELECT NULL)) ID
FROM #CURVE c
) t
PIVOT(MAX([Value]) FOR ID IN ([1], [2], [3]])) p
I am trying to split a 'grand total' value into two columns in my query but doing so by maintaining one row in the results. I am currently using two different CASE statements to do so but it ends up creating two rows for each result - each one containing a NULL. Is there anyway to do this and only return one one row of results with the grand total split out by the conditions specified?
Example is I have a material that has Quantity 'Blank Qty' of 38 units and an 'Uncovered Qty' of 8 units for a grand total of 46. I would like to see this in one row - but with the code below I get two rows for this material - one for each type of qty. I have looked into PIVOT but doesn't seem like it would do the trick.
CASE
WHEN MRP.STOCK_TYPE = 'A'
THEN SUM(MRP.QUANTITY)
END AS 'Uncovered Qty',
CASE WHEN MRP.STOCK_TYPE <> 'A'
THEN SUM(MRP.QUANTITY)
END AS 'Blank Qty'
returns:
one row with a value of 'uncovered qty' = NULL and 'blank qty' = 38
one row with a value of 'uncovered qty = 8 and 'blank qty = NULL
Is there some way to get this to return in a single row and avoid the NULL
You can bring the condition into the SUMs and that will give you both values in one row:
SUM (CASE WHEN MRP.STOCK_TYPE = 'A' THEN MRP.QUANTITY ELSE 0 END) AS 'Uncovered Qty',
SUM (CASE WHEN MRP.STOCK_TYPE <> 'A' THEN MRP.QUANTITY ELSE 0 END) AS 'Blank Qty'
add isnull() on your subquery to return 0 for nulls and sum() the results again.
select sum(t1.[Uncovered Qty]) as [Uncovered Qty], sum(t1.[Blank Qty]) as [Blank Qty]
from (select
CASE WHEN MRP.STOCK_TYPE = 'A'
THEN ISNULL(SUM(MRP.QUANTITY), 0)
END AS 'Uncovered Qty',
CASE WHEN MRP.STOCK_TYPE <> 'A'
THEN ISNULL(SUM(MRP.QUANTITY), 0)
END AS 'Blank Qty'
from table) t1
HI I am unable to filter materials that belong to only specific list.
Select material
from price
where region='04'
and pricelist ='5'
and pricelist not in ('4','6','7');
I want only those materials which are unique only in pricelist 5 and not in any other pricelists. how can i get this?
You might try something like this (alternately, you could do a self-join, but I think this is just as easy, if not easier, to understand):
SELECT material
FROM price a
WHERE region = '04'
AND pricelist = '5'
AND NOT EXISTS ( SELECT 1 FROM price b
WHERE b.material = a.material
AND b.region = a.region
AND b.pricelist != a.pricelist )
What the above will do will find values of material in region '04' where the pricelist is '5' while excluding those same materials in the same region but on a different price list.
Your current query will only return results where pricelist = 5 -- the not in statement is irrelevant unless it exclude that record. It sounds like you want to return any material which matches on the 5, but doesn't have any other non-5 matches.
One option is to use exist. Here's another option using conditional aggregation with max and case which eliminates the need for multiple queries:
select material
from (
select material,
max(case when pricelist = '5' then 1 else 0 end) haspl5,
max(case when pricelist != '5' then 1 else 0 end) hasothers
from price
where region='04'
group by material
) t
where haspl5 = 1 and hasothers != 1
SQL Fiddle Demo
I need help with a query. Consider the following table:
I need to select first the sum of each Code from table. I am doing it with simple sum and group by statement. Then I have to subtract the results from each code sum where type='r'
1) Say for first part of query, we will get 2 rows from SUM (one with total USD and one with total YEN)
2) Now I need to subtract from these results the corresponding USD, YEN value which has Type='r'
I have to do it inside SQL and not a stored procedure.
Why not use a WHERE statement to say WHERE Type != 'r' so that those values never even get added to sum in the first place...
SELECT `Code`, SUM(`Amount`) AS `Total`
FROM `Table`
WHERE `Type` != 'r'
GROUP
BY `Code`;
Something like that.
select code, l.amount - r.amount
from
(select code, sum(amount) as amount from my_table group by code) l
left join (select code, sum(amount) as amount from my_table where type = 'r' group by code) r
on l.code = r.code
You can do this in a single, simple query:
select
code,
sum(case when type = 'r' then (-1 * amount) else amount end) as sum
from
yourtable
group by
code
Basically, you're changing the sign of the rows that have type = 'r', so when you sum all rows for a particular code you'll get the correct answer.
Does it have to be a single query?
I'd say SUM the total, then SUM the subcategory where Type='r', then subtract one from the other.
You could do this in one line of SQL, but I'm pretty sure it would be either joining the table with itself or using a subquery. Either way, it's doing the same amount of work as the above.
Try:
select code,
sum(amount) gross_total,
sum(case when type = 'r' then amount else 0 end) type_r_total,
sum(case when type != 'r' then amount else 0 end) net_total
from yourtable
group by code;
to see the overall totals, type R only totals and non-type R totals for each currency on one row per currency, in a single pass.
I hope I'm explaining this well. I'm struggling with this query:
I have this table that is something like this:
InvoiceNum
Amount
Type - where type could be item, shipping or tax.
So what I want returned is one row per invoice: InvoiceNum, ItemAmount, ShippingAmount, TaxAmount.
Here's an example:
Invoicenum Amount Type
1 $32 Item
1 $2 Shipping
1 $1 Tax
I would want returned:
InvoiceNum ItemAmount ShippingAmount TaxAmount
1 $32 $2 $1
You can summarize rows with group by, and you can select specific rows using case:
select InvoiceNum
, sum(case when Type = 'Item' then Amount end) as ItemAmount
, sum(case when Type = 'Shipping' then Amount end) as ShippingAmount
, sum(case when Type = 'Tax' then Amount end) as TaxAmount
from YourTable
group by
InvoiceNum
The case statement returns null by default, and sum ignores nulls.
You can do this with group by and sum tricks (max works too) as #Andomar shows.
Alternatively, Microsoft SQL Server supports syntax for a PIVOT operation that helps a bit in this type of query. You still have to hard-code the column names though.
SELECT InvoiceNum, [Item] AS ItemAmount, [Shipping] AS ShippingAmount, [Tax] AS TaxAmount
FROM
(SELECT InvoiceNum, Amount, Type FROM InvoiceTable ) i
PIVOT
(
MAX(Amount)
FOR Type IN ([Item], [Shipping], [Tax])
) AS pvt;