SQL to pivot a field with CASE WHEN - sql

My table has fields: Item, AttributeNo_, AttrbuteValue. Each AttributeNo_ has a matched AttributeName.
e.g.
Item, AttributeNo_, AttributeValue
A, 1, Yellow
A, 2, Round
……
(AttributeNo_ 1 means color, 2 means shape as AttributeName)
This is what I'm trying to achieve:
Item, Color, Shape
A, Yellow, Round
……
My code is:
select Item,
case when AttributeNo_=1 then AttributeValue end AS Color,
case when AttributeNo_=2 then AttributeValue end AS Shape
from table;
The result is like:
Item, Color, Shape
A, Yellow, Null
A, Null, Round
……
How can I achieve the correct result?
Thanks in advance!

Use aggregation:
select Item,
max(case when AttributeNo_ = 1 then AttributeValue end) AS Color,
max(case when AttributeNo_ = 2 then AttributeValue end) AS Shape
from table
group by Item;

Related

Select statement with column based on another column values of same table

I need select statement like
select Invoice, Original Color,Product,Option Color, Result_column from table
where Result_column value is based on below condition
Available options are only 3 colors, RED, GREEN and BLUE.
if all Option_Colors in invoice are green then result column will be
GREEN.
if all Option_Colors in invoice are blue then result column will be
BLUE
if all Option_Colors in invoice are red then result column will be
RED
In case of mixture of colors in Option_Colors of invoice, then
whatever Color Original_Color column shows.
In case Option_Colors is not RED, GREEN or BLUE then whatever Color
Original_Color column shows.
Try this.
select Invoice, OriginalColor, OptionColor,
case
when OptionColor not in ('RED', 'BLUE', 'GREEN') then OriginalColor
when Result_Column > 1 then OriginalColor
else OptionColor end as Result_Column
from (
select i.Invoice, i.OriginalColor, i.OptionColor,
(select count(distinct OptionColor) from table ic where ic.Invoice = i.Invoice) as Result_Column
from table i
) temp
You can make use of case statement, that would be easier as well.
select Invoice, Original_Color,Product,Option_Color, case when Option_Color not in
('RED', 'GREEN', 'BLUE') THEN Original_Color else Option_Color end Result_column from
table
You can try:
with mytablecnt(Invoice, Cnt) as
(
select Invoice, count(distinct OptionColor) as Cnt
from mytable
group by Invoice
)
select t1.Invoice, t1.OriginalColor, t1.OptionColor,
case
when t2.Cnt = 1 then OptionColor
when t2.Cnt != 1 then OriginalColor
end as ResultColumn
from mytable t1
left join mytablecnt t2
on t1.Invoice = t2.Invoice
order by Invoice

Transpose row into columns with If statement

I am trying to transpose certain row values into columns. Below is what my table looks like:
ID Item Color Quantity
1 Shoe Red
1 Shirt 3
1 Hat Black
1 Socks 2
1 Pants Red
What I want the table to look like is this:
ID Shoe Shirt Hat Socks Pants
1 Red 3 Black 2 Red
Below is the code I am using:
select Max(Case When [Item] = 'Shoe' Then Color End) as Shoe
,Max(Case When [Item] = 'Shirt' Then Quantity End) as Shirt
,Max(Case When [Item] = 'Hat' Then Color End) as Hat
,Max(Case When [Item] = 'Socks' Then Quantity End) as Socks
,Max(Case When [Item] = 'Pants' Then Color End) as Pants
From Inventory
The problem with my code is sometimes the value for the row is in column Color and other times it's in column Quantity. I would like to be able to use only to column with a value. My real select statement has over 50 Max(Case) statements, so if there is someway I can do an overarching if statement and not have to do one for each line that would be great!
If you want a dynamic version.
In the sub-query below, you'll notice that we use CONCAT(), which will handle NULL values appropriately.
Declare #Filter varchar(100) = 'Shoe,Socks'
Declare #SQL varchar(max)
Select #SQL = 'Select ID,' + '['+Replace(#Filter,',','],[')+']' + '
From (
Select ID
,Item
,Value = concat(NullIf(Color,''''),NullIf(Quantity,0))
From Inventory
Where charindex('',''+Item+'','','','+#Filter+','')>0
) A
Pivot (max(Value) For Item in (' + '['+Replace(#Filter,',','],[')+']' + ') ) p'
Exec(#SQL);
EDIT:
Added NullIf() to the concat() to trap "empty" values.
How about using a common table expression (CTE) to find the non null value column then PIVOT on the Item if you know all of your Items up front. It should be noted that this only works if the other value is null, otherwise you would need to check for '' or 0.
;WITH CTE
AS
(
SELECT ID, Item, COALESCE(Color, CAST(Quantity AS VARCHAR(10))) AS Value
FROM Inventory
)
select * from CTE
pivot (max (Value) for Item in ([Shoe],[Shirt],[Hat],[Socks],[Pants])) AS c
You probably need a dictionary which maps an item to a value column. For example
select Max(Case When [Item] = 'Shoe' Then
Case col when 'Color' then Color else Quantity End
End) as Shoe
,Max(Case When [Item] = 'Shirt' Then
Case col when 'Color' then Color else Quantity End
End) as Shirt
,Max(Case When [Item] = 'Hat' Then
Case col when 'Color' then Color else Quantity End
End) as Hat
,Max(Case When [Item] = 'Socks' Then
Case col when 'Color' then Color else Quantity End
End) as Socks
,Max(Case When [Item] = 'Pants' Then
Case col when 'Color' then Color else Quantity End
End) as Pants
From (
select i.*, col
from Inventory i
join (
values ('Shoe', 'Color')
,('Shirt', 'Quantity')
,('Hat', 'Color')
,('Socks', 'Quantity')
,('Pants', 'Color')
) dict (itm, col) on dict.itm=t.item
) t

How to SELECT COUNT multiple values in one column

rather a newbie at SQL, so please be gentle....as I think this is a basic one.
I'm trying to write a query with multiple (13) counts, based off Column1. The 1st Count is the over-all total. And then the 12 others are filtered by Color. I can get my results by doing multiple Counts all in one query, but this gives me 13 rows of data. The goal here is to get everything on just one row. So, almost like each count would be its own column. Here is an example of the data model
Database = CARS, Table = TYPES, Column1 = LICENSE, Column2 = COLOR
SELECT COUNT (LICENSE) AS 'Total ALL Cars'
FROM CARS.TYPES WITH (NOLOCK)
SELECT COUNT (LICENSE) AS 'Total RED Cars'
FROM CARS.TYPES WITH (NOLOCK)
WHERE COLOR = 'RED'
And on & on & on for each remaining color. This works, but again, I'm trying to streamline it all into one row of data, IF possible. Thank you in advance
You simply need to include color in select statement and group by it to count cars of each color.
SELECT Color, Count(*)
FROM CARS.TYPES WITH(NOLOCK)
GROUP BY Color
or
SELECT COUNT(CASE WHEN Color = 'RED' THEN 1
ELSE NULL
END) AS RedCars
,COUNT(CASE WHEN Color = 'BLUE' THEN 1
ELSE NULL
END) AS BlueCars
,COUNT(*) AS AllCars
FROM CARS.TYPES WITH ( NOLOCK )
You can do this with a conditional SUM():
SELECT SUM(CASE WHEN Color = 'Red' THEN 1 END) AS 'Total Red Cars'
,SUM(CASE WHEN Color = 'Blue' THEN 1 END) AS 'Total Blue Cars'
FROM CARS.TYPES
If using MySQL you can simplify further:
SELECT SUM(Color = 'Red') AS 'Total Red Cars'
,SUM(Color = 'Blue') AS 'Total Blue Cars'
FROM CARS.TYPES
Or with PIVOT
SELECT RED + BLUE + GREEN AS total,
RED,
BLUE,
GREEN
FROM CARS.TYPES PIVOT (COUNT (LICENSE) FOR COLOR IN ([RED], [BLUE], [GREEN])) P
SELECT SUM(Al) AllCount, SUM(Red) RedCount, SUM(Green) GreenCount, ...
(
SELECT 1 AS Al
, CASE WHEN Color = 'Red' THEN 1 ELSE 0 END AS Red
, CASE WHEN Color = 'Green' THEN 1 ELSE 0 END AS Green
...
FROM CARS.Types
)

SQL display summation of data in row

I have a table like this
No.
--
b
r
g
g
r
b
r
g
I want resultset like below
Type of color | Ocurrence
Blue 2
green 3
red 3
TOTAL 8
Please help
Sounds like CASE and GROUP BY would be what you need;
SELECT
CASE WHEN color = 'r' THEN 'red'
WHEN color = 'g' THEN 'green'
WHEN color = 'b' THEN 'blue'
END "Type of color", COUNT(color) "Occurrence"
FROM Table1
GROUP BY color
ORDER BY color;
An SQLfiddle to test with.
To get a total, one (not necessarily the simplest) way is to just UNION with the total;
WITH cte AS (
SELECT
CASE WHEN color = 'r' THEN 'red'
WHEN color = 'g' THEN 'green'
WHEN color = 'b' THEN 'blue'
END "Type of color", COUNT(color) "Occurrence"
FROM Table1
GROUP BY color
UNION
SELECT 'TOTAL',COUNT(*)
FROM Table1
)
SELECT * FROM cte
ORDER BY CASE WHEN "Type of color" = 'TOTAL' THEN 1 END;
Another SQLfiddle.
Joachim's answer is fine, except there is an easier way to get the total using rollup:
SELECT
CASE WHEN color = 'r' THEN 'red'
WHEN color = 'g' THEN 'green'
WHEN color = 'b' THEN 'blue'
when color is NULL then 'Total'
END "Type of color", COUNT(*) "Occurrence"
FROM Table1
GROUP BY color with rollup
ORDER BY (case when color is null then 1 else 0 end), color

Please show me how to write a unique sql statement

Below are the tables I need to pull data from - I only included columns to be used here in this example:
Maintable:
mainkey, account
-----------------
1, 100
2, 200
3, 300
Childtable:
linkedkeytomain, type, color
---------------------------
2, b, blue
2, y, yellow
2, r, red
2, g, green
2, w, white
My goal is to be able to write a select that will only show one line of data Where Type = 'b' and Type = 'w' and Type = 'r' only:
For instance,
Account, c1, c2, c3
---------------------
200, blue, white, red
Can someone please show me how to obtain this complex select. Many thanks in advance.
blumonde
Your problem is that you need to pivot the groups. Here is a simple way:
select account,
max(case when seqnum = 1 then color end) as color1,
max(case when seqnum = 2 then color end) as color2,
max(case when seqnum = 3 then color end) as color3
from (select account, color,
row_number() over (partition by account order by color) as seqnum
from maintable mt join
childtable ct
on ct.linkedkeytomain = mt.mainkey
) t
group by account