SQL display summation of data in row - sql

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

Related

Sort out IDs when hitting a case

How to sort out ID´s when i have a table like
CAR
ID COLOR
1 Red
1 Black
2 BLUE
2 Black
3 Yellow
3 Red
My goal is, that all IDs who have the color "Red" get thrown out, so that just ID = 2 is my result. With my SQL i can find the IDs which have the Color Red with Filter = 1 but they still appear because ID = 1 can also have Black(or ID = 3 can have yellow) so that Filter = 0 and gets passed.
with SORTOUT as
(
ID,
CASE WHEN
COLOR = RED THEN 1
ELSE 0
END AS FILTER
FROM TABLE
)
SELECT * FROM ID_TABLE T1
JOIN SORTOUT T2 on (T1.ID = T2.ID)
WHERE FILTER = 0
If you only want the id, use aggregation:
select id
from id_table
group by id
having sum(case when color = 'RED' then 1 else 0 end) = 0;
If you want the original rows, you can use not exists:
select i.*
from id_table i
where not exists (select 1
from id_table i2
where i2.id = i.id and i2.color = 'RED'
);
You can use simple select query to achieve this,
SELECT * FROM ID_TABLE WHERE COLOR != 'Red';
If you still need CASE statement, you can use below
SELECT ID, COLOR,
CASE WHEN COLOR = 'Red' THEN 1 ELSE 0 END AS Val
FROM ID_TABLE WHERE CASE WHEN COLOR = 'Red' THEN 1 ELSE 0 END = 0;
Or
SELECT ID, COLOR FROM
(SELECT ID, COLOR,
CASE WHEN COLOR = 'Red' THEN 1 ELSE 0 END AS Val
FROM ID_TABLE) qry
WHERE Val = 0;

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

SQL match if not 0 or > 4

Here is my issue.
I have 4 tables as example (Shape -> ShapeDetails -> ShapeSize -> ShapeColor)
Basically each time I create a new Shape there is new line ShapeColor created( and for each colors I selected is created new line in the table ShapeColor) Inconvenient I know but the software I have to use has been designed like this.
So , a Shape can have a lot of colors but I would like to match based on the "name" of the color those which have color "red", "pink","blue" BUT if one of them have "red","pink","blue" and "yellow" in this case this one should not be matched.
I would like to match those between 1 and/or 3 colors.
Example (Colors: red,pink,blue,yellow) :
0 0 0 0 (none of these colors = NOK) not in the resulstSet
1 0 0 0 (only red but not pink blue yellow = OK) Match in the resultSet
0 1 0 0 (only pink but not red blue yellow = OK) Match
1 1 0 0 (only red pink but not blue and yellow = OK) Match
1 0 1 0 ...
1 1 1 1 (all of these colors = NOK) not in the resultsSet
btw, I use some joins to get to ShapeColor
I don't know how can I solve this problem with one SQL query, any kind of help will be very appreciated
SELECT s.id
FROM shape s INNER JOIN shape_color sc ON s.id=sc.id
GROUP BY s.id
HAVING
SUM(CASE WHEN sc.color='red' OR sc.color='pink' OR sc.color='blue' 1 ELSE 0 END) >0
AND
HAVING SUM(CASE WHEN sc.color='yellow' 1 ELSE 0 END) = 0
HAVING is applied to grouped results
if sum of valid colors is >0 that means one of the 3 valid colors exists for the shape
if sum of invalid color is >0 thah means yellow color exist
So you get shapes where one (or more) of valid colors exists and invalid color does not exist
UPDATE:
SELECT s.id
FROM shape s INNER JOIN shape_color sc ON s.id=sc.id
GROUP BY s.id
HAVING
SUM(CASE WHEN sc.color='red' OR sc.color='pink' OR sc.color='blue' OR sc.color='yellow' 1 ELSE 0 END) >0
AND
SUM(CASE WHEN sc.color='red' OR sc.color='pink' OR sc.color='blue' OR sc.color='yellow' 1 ELSE 0 END) <=3
Assuming the colors are independent, you can do:
SELECT sc.shape_id
FROM shape_color sc join
color c
ON sc.color_id = c.color_id
WHERE c.color in ('red', 'pink', 'blue', 'yellow')
GROUP BY sc.shape_id
HAVING COUNT(*) < 4;
(Your column names aren't clear but you should get the idea.)
By looking in shape_color, you are eliminating the first condition -- a color is needed. This then just checks that there are fewer than 4 colors. Implicitly, there is at least one, but you could add HAVING COUNT(*) > 0 AND COUNT(*) < 4.
If you find the solution with GROUP BY and HAVING could be confusing, simple first concatenate the colors in a string using LISTAGG.
Note that an INNER JOIN is used eliminate the shapes without colors (here 4 - see sample data below).
Also the WHERE predicate limits only the relevant colors.
select s.shape_id,
LISTAGG(c.color, ',') WITHIN GROUP (ORDER BY c.color) color_lst
from shape s
join shape_color c
on s.shape_id = c.shape_id
where c.color in ('red', 'pink', 'blue', 'yellow')
group by s.shape_id
;
SHAPE_ID COLOR_LST
---------- ---------------------------
1 blue,pink,red,yellow
2 red
3 blue,pink,yellow
You task is than as simple as eliminate the only negative case of all four colors:
with colors as (
select s.shape_id,
LISTAGG(c.color, ',') WITHIN GROUP (ORDER BY c.color) color_lst
from shape s
join shape_color c
on s.shape_id = c.shape_id
where c.color in ('red', 'pink', 'blue', 'yellow')
group by s.shape_id
)
select shape_id
from colors
where color_lst != 'blue,pink,red,yellow'
SHAPE_ID
----------
2
3
You shoud take some care to check, that the colors within a shape are unique. If not you must add a subquery that distincts the colors within shape. The same is valid also for the HAVING based solutions.
Sample Data
create table shape as
select 1 shape_id from dual union all
select 2 shape_id from dual union all
select 3 shape_id from dual union all
select 4 shape_id from dual;
create table shape_color as
select 1 shape_id, 'red' color from dual union all
select 1 shape_id, 'pink' color from dual union all
select 1 shape_id, 'blue' color from dual union all
select 1 shape_id, 'yellow' color from dual union all
select 2 shape_id, 'red' color from dual union all
select 3 shape_id, 'pink' color from dual union all
select 3 shape_id, 'blue' color from dual union all
select 3 shape_id, 'yellow' color from dual;

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
)

Merging tables into New table while retaining information

I apologize in advance as the title is not very descriptive.
I have approximately 40+ tables each with the same exact table layout columns, and data save for one column. I would like to take that column which is not the same across all the tables and merge them into one table. Confusing? Let me illustrate..
SRCTbl01:
ID TYPE COLR1 INSTOCK
-----------------------
1 B RED YES
2 B BLUE YES
3 P GREEN NO
4 B BLACK YES
SRCTbl02:
ID TYPE COLR1 INSTOCK
-----------------------
1 B RED YES
2 B BLUE NO
3 P GREEN YES
4 B BLACK YES
SRCTbl03:
ID TYPE COLR1 INSTOCK
-----------------------
1 B RED YES
2 B BLUE NO
3 P GREEN NO
4 B BLACK NO
RESULT: (Type P to be excluded)
ID TYPE COLR1 SRCTbl01 SRCTbl02 SRCTbl03
----------------------------------------------
1 B RED YES YES YES
2 B BLUE YES NO NO
4 B BLACK YES YES NO
And finally after all that I'd like to make the table look something like this:
INSTOCK Table:
Customer RED BLUE BLACK
---------------------------
SRCTbl1 YES YES YES
SRCTbl2 YES NO YES
SRCTbl3 YES NO NO
I'm not entirely sure whether I can directly manipulate the tables into looking like the final iteration so I thought I should ask how to get it to the first Result as to me it seems simpler.
Thank you for the help, I've spent a full 8 hours on this and have yet to find a way to achieve it so I have come here to ask the experts.
EDIT: To clarify, I have had zero success in achieving the results I illustrated above. I have tried using SELECT .. Union SELECT, and FULL JOINS.
Using this code resulted in duplicates ( I was trying to just get the INSTOCK)
SELECT 01.INSTOCK, 02.INSTOCK, 03.INSTOCK
FROM dbo.SRCTbl01 AS 01, dbo.SRCTbl02 AS 02, dbo.SRCTbl03 AS 03
WHERE 01.TYPE='B'
I tried very many but this is probably the closest I got.
you could do something like that, all in one :
You first flatten with union, then take the max 'instock' for each color by customer (MAX will work as 'YES' > 'NO')
select Customer, MAX(RED) as RED, MAX(BLUE) as BLUE, MAX(BLACK) as BLACK
FROM(
SELECT 'SRCTbl01' as Customer,
CASE WHEN COLR1 = 'RED' then INSTOCK ELSE 'NO' END as RED,
CASE WHEN COLR1 = 'BLUE' then INSTOCK ELSE 'NO' END as BLUE,
CASE WHEN COLR1 = 'BLACK' then INSTOCK ELSE 'NO' END as BLACK
FROM SRCTbl01
WHERE Type <> 'P'
UNION
SELECT 'SRCTbl02' as Customer,
CASE WHEN COLR1 = 'RED' then INSTOCK ELSE 'NO' END as RED,
CASE WHEN COLR1 = 'BLUE' then INSTOCK ELSE 'NO' END as BLUE,
CASE WHEN COLR1 = 'BLACK' then INSTOCK ELSE 'NO' END as BLACK
FROM SRCTbl02
WHERE Type <> 'P'
UNION
SELECT 'SRCTbl03' as Customer,
CASE WHEN COLR1 = 'RED' then INSTOCK ELSE 'NO' END as RED,
CASE WHEN COLR1 = 'BLUE' then INSTOCK ELSE 'NO' END as BLUE,
CASE WHEN COLR1 = 'BLACK' then INSTOCK ELSE 'NO' END as BLACK
FROM SRCTbl03
WHERE Type <> 'P'
) as a
GROUP BY Customer
(You just need to add a CREATE TABLE INSTOCK as <codegiven>)
see SqlFiddle
Using UNION and PIVOT, something like this should do what you want (PIVOT should work on SQL Server 2005 and newer):
SELECT Customer, [Red], [Blue], [Black]
FROM (
SELECT 'SRCTbl01' AS Customer, COLR1, INSTOCK FROM SRCTbl01 WHERE Type <> 'P'
UNION
SELECT 'SRCTbl02' AS Customer, COLR1, INSTOCK FROM SRCTbl02 WHERE Type <> 'P'
UNION
SELECT 'SRCTbl03' AS Customer, COLR1, INSTOCK FROM SRCTbl03 WHERE Type <> 'P'
/* UNION ... */
) AS SRC
PIVOT (
MAX(INSTOCK)
FOR COLR1 IN ([Red], [Blue], [Black])
) AS pvt