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

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

Related

How to build a CASE statement in SQL that identifies when there are multiple DIFFERENT values for a specific item?

Here is a simple example of what I'm trying to achieve:
Essentially I want to take a data set like this:
raw data
Into this:
output
I'm thinking some sort of CASE statement to check for when there are multiple colors for any single fruit, THEN 'Multiple' ELSE "Color", but not sure how to build that logic to check for multiple different values for a single item. Thanks in advance for the help!
declare #table table
( fruit varchar(250),
color varchar(250)
)
insert into #table (fruit, color)
values
('banana', 'yellow')
, ('banana', 'yellow')
, ('apple', 'red')
, ('apple', 'green')
select distinct t.fruit, case when d.color = 1 then t.color else 'multiple' end as color from #table t
left join
(
select fruit, count(distinct color) as color from #table
group by fruit
) d on d.fruit = t.fruit
That one works. Using count distinct to get the amount of colors, then a distinct on the outer select.
select fruit
,case when count(distinct Color) > 1 then 'Multiple' else max(color) end as Color
from t
group by fruit
fruit
Color
Apple
Multiple
Banana
Yellow
Cherry
Multiple
Orange
Orange
Fiddle

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

Select records based on column priority

First of all, the title of this question is horrible, but I didn't find a better way to describe my issue.
There's probably a very easy way to do this, but I couldn't figure it out. This is very similar to this question, but I'm running on sqlite3 (iOS) so I suspect my options are much more limited.
I have a table with product records. All records have an ID (note: I'm not talking about the row ID, but rather an identification number unique to each product). Some products may have two entries in the table (both with the same ID). The only difference would be in a special column (let's say column COLOUR can be either RED or GREEN).
What I want to do is create a list of unique products based on the value of COLOUR, with priority to GREEN if both GREEN and RED records exist for the same product.
In short, if I have the following case:
id PRODUCT ID COLOUR
1 1001 GREEN
2 1002 GREEN
3 1002 RED
4 1003 RED
I would like my SELECT to return the rows 1, 2 and 4. How can I achieve this?
My current approach is to have separate tables, and do the join manually, but obviously this is a very bad idea..
Note: I've tried to use the same approach from here:
SELECT *
FROM xx
WHERE f_COLOUR = "GREEN"
UNION ALL
SELECT *
FROM xx
WHERE id not in (SELECT distinct id
FROM xx
WHERE f_COLOUR = "GREEN");
But the result I'm getting is rows 1,2,3,4 instead of just 1,2,4. What am I missing?
Edit: One more question please: how can this be made to work with a subset of records, ie. if instead of the entire table I wanted to filter some records?
For example, if I had something like SELECT * FROM table WHERE productID LIKE "1%" ... how can I retrieve each unique product, but still respecting the colour priority (GREEN>RED)?
Your query is nearly correct. Just use PRODUCTID and not ID.
SELECT *
FROM xx
WHERE f_COLOUR = "GREEN"
UNION
SELECT *
FROM xx
WHERE PRODUCTID not in
(SELECT PRODUCTID
FROM xx
WHERE f_COLOUR = "GREEN");
SQLFiddle Demo
Try this
SELECT *
FROM xx
WHERE COLOUR = 'GREEN'
UNION
SELECT *
FROM xx WHERE P_Id not in
(SELECT P_Id
FROM Persons
WHERE COLOUR = 'GREEN');
See ALSO SQL FIDDLE DEMO
I just want to offer that you can do this with a group by:
select (case when sum(case when colour = 'Green' then 1 else 0 end) > 0
then max(case when colour = 'Green' then id end)
else max(case when colour = 'Red' then id end)
end) as id,
product_id
(case when sum(case when colour = 'Green' then 1 else 0 end) > 0 then 'Green'
else 'Red'
end) as colour
from t
group by product_id
You can have it like this
WITH PriorityTable
AS
(
SELECT T.*,
ROW_NUMBER() OVER (PARTITION BY T.ID
ORDER BY PT.ColorPriority ) PriorityColumn
FROM XX AS T
INNER JOIN (
SELECT 'RED' AS f_COLOUR , 1 AS ColorPriority
UNION
SELECT 'GREEN' AS f_COLOUR , 2 AS ColorPriority
) AS PT
ON T.f_COLOUR = PT.f_COLOUR
)
SELECT * FROM PriorityTable
WHERE PriorityColumn = 1

SQL Join Tables

Table one contains
ID|Name
1 Mary
2 John
Table two contains
ID|Color
1 Red
2 Blue
2 Green
2 Black
I want to end up with is
ID|Name|Red|Blue|Green|Black
1 Mary Y Y
2 John Y Y Y
Thanks for any help.
Thanks for the responses. I'm going to re-post this with some additional info about exactly what I'm trying to do that may complicate this. Can someone close this?
If you use T-SQL you can use PIVOT (http://msdn.microsoft.com/en-us/library/ms177410.aspx)
Here is query I used:
declare #tbl_names table(id int, name varchar(100))
declare #tbl_colors table(id int, color varchar(100))
insert into #tbl_names
select 1, 'Mary'
union
select 2, 'John'
insert into #tbl_colors
select 1, 'Red'
union
select 1, 'Blue'
union
select 2, 'Green'
union
select 2, 'Blue'
union
select 2, 'Black'
select name,
case when [Red] is not null then 'Y' else '' end as Red,
case when [Blue] is not null then 'Y' else '' end as Blue,
case when [Green] is not null then 'Y' else '' end as Green,
case when [Black] is not null then 'Y' else '' end as Black
from
(
select n.id, name, color from #tbl_names n
inner join #tbl_colors c on n.id = c.id
) as subq
pivot
(
min(id)
FOR color IN ([Red], [Blue], [Green], [Black])
) as pvt
And here is output:
John Y Y Y
Mary Y Y
I can use a CASE statement with a subquery to input the Y values.
select ID, Name,
case
when exists (select * from Colors C where C.ID = N.ID and Color = 'Red') then
'Y'
else
NULL
end
,
case
when exists (select * from Colors C where C.ID = N.ID and Color = 'Blue') then
'Y'
else
NULL
end
,
case
when exists (select * from Colors C where C.ID = N.ID and Color = 'Green') then
'Y'
else
NULL
end
,
case
when exists (select * from Colors C where C.ID = N.ID and Color = 'Black') then
'Y'
else
NULL
end
from Names N
I think you're going to have to end up with something like this :
SELECT t1.ID,
t1.Name,
CASE
WHEN red.ID IS NULL THEN ''
ELSE 'Y'
END As Red,
CASE
WHEN blue.ID IS NULL THEN ''
ELSE 'Y'
END As Blue
FROM Table1 t1
LEFT JOIN Table2 Red
ON t1.ID = Red.ID AND Red.Color = 'Red'
LEFT JOIN Table2 Blue
ON t1.ID = Blue.ID AND Blue.Color = 'Blue'
MS Sql does not support PIVOT queries like MS Access.
As other commenters have pointed out, you don't display exactly how you are linking people and colors. If you are using a linking table (person_id, color_id) then there is no way to solve this problem in standard SQL since it requires a pivot or cross-tabulation, which is not part of standard SQL.
If you are willing to add the condition that the number of colors is limited and known and design time, you could come up with a solution using one join for each color and CASE or IF functions in the SQL. But that would not be elegant and, furthermore, I wouldn't trust that condition to stay true for very long.
If you are able to come up with a different way of storing the color linking information you might have more options for producing the output you want, but a different storage technique implies some degree of denormalization of the database which could well cause other difficulties.
Otherwise, you will have to do this in a stored procedure or application code.
Contrary to what some other posters have said; I see no need for a third table. If colors are a well known enumeration in you application then you don't need a "Color" table.
What you are looking for is a PIVOT like this one.