Trying to get this result from a table with duplicates
red
red
red
blue
green
to
blue
green
Totally omitting all the records that has duplicates and only bringing in the unique records
Use GROUP BY and HAVING clause...
select color
from table1
group by color
having count(color) = 1
If you need more than just the colours.
select *
from paintmess
where colour in (
select colour
from paintmess
group by colour
having count(*)=1
);
id
colour
4
blue
5
green
db<>fiddle here
Let's say there is this table colors
id
source
1
red
1
green
1
orange
2
red
2
red
3
black
3
green
4
red
5
green
What I want is the list of all id that have as only source the value 'red', so 2 and 4.
To be clear
select distinct id from colors where source = 'red'
would give 1,2 and 4, where 1 has 'green' and 'orange' in addition to 'red', so no.
Here the SQL to create the table
create temp table colors as
select *
from (values (1, 'red'),(1, 'green'),(1, 'orange'),(2,'red'),(2, 'red'),(3, 'black'),(3,'green'),(4,'red'),(5,'green'))
as t (id,source)
How to query this?
Use aggregation:
select id
from t
group by id
having count(*) filter (where color = 'red') = count(*);
I managed to find a query, but it seems so complicated and unpractical:
with colors_sint as (
--This is the list of distinct sources for every id
select id, source
from colors
group by id, source
), only_red as (
--Here I check which id has only one distinct source
select id, count(*) as n_sources
from colors_sint
group by id
having count(*) = 1
)
--among those id that have only one source, I take only those that have only red as source
select id
from colors_sint
where id in (select id from only_red)
and "source" = 'red'
Maybe someone has better ideas?
I need to write a sql query that will return the row that has the max value per user id.
In my table I have 5 columns (Blue, Red, Green, Blue, Orange, Yellow) that store a numeric value. And in my table a user can appear on multiple rows.
For each user id, I need to determine which of the 5 columns (Blue, Red, Green, Blue, Orange, Yellow) has the highest value per user id. I have tired a few things, but am stuck.
If I need to provide additional information, please let me know.
See table below
If you want to get fancy you can look into Using GROUP BY with ROLLUP, CUBE, and GROUPING SETS on groups but a simple approach is to flatten the list. You can use a pivot or union like example below. Then use row_number to get the first in the list.
declare #tbl table (UserId int, Blue int, Red int, Green int, Orange int, yellow int)
insert into #tbl (UserId, Blue, Red, Green, Orange, Yellow)
values
(1, 1,9,4,3,4),
(2, 2,5,4,3,5),
(3, 3,4,9,3,3),
(4, 9,4,6,3,9),
(5, 2,4,5,2,9)
;
with flattenedCte as (
select UserId, Blue [Count], 'Blue' Color from #tbl
union
select UserId, Red [Count], 'Red' Color from #tbl
union
select UserId, Green [Count], 'Green' Color from #tbl
union
select UserId, Orange [Count], 'Orange' Color from #tbl
union
select UserId, Yellow [Count], 'Yellow' Color from #tbl
)
,Sub as (
select
UserId,
Color,
max([Count]) [Max of Count],
ROW_NUMBER() over (partition by UserId order by max([Count]) desc) [Row number]
from flattenedCte
group by UserId,Color
)
select * from Sub where [Row number] = 1
could be using case when
select
user_id
, case when (blue > Red AND Blue > Green AND Blue > Orange AND Blue > Yellow) THEN Blue ELSE null END
, case when (Red > Blue AND Red > Green AND Red > Orange AND Red > Yellow) THEN Red ELSE null END
, case when (Green > Blue AND Green > Red AND Green > Orange AND Green > Yellow) THEN Green ELSE null END
, case when (Orange > Blue AND Orange > Red AND Orange > Green AND Orange > Yellow) THEN Orange ELSE null END
, case when (Yellow > Blue AND Yellow > Red AND Yellow > Green AND Yellow > Orange) THEN Yellow ELSE null END
from my_table
In your case maybe a case when coupled with a subtable might help, altough there might be a better solution out there.
This post here might help you out.
Let's say I have two tables; table A and table shown below:
A
Color ID
Blue 1
Green 2
Red 3
B
Color ID
Blue 1
Brown 2
Red 3
If I were to attempt to join them using a full join, the result would depend on which table I use in the select statement. For example the following query would produce the following result
select A.color, count(*)
from A
full join B on a.color = B.color
group by 1
order by 1
color count
Blue 1
Green 1
Red 1
1
If I decided to use B.color in the select statement instead of A.color, I would get the result below:
color count
Blue 1
Brown 1
Red 1
1
How would I get the resultset to include all values for color. I know I could accomplish using unionall, and I could use a case statement in the select statement to use one when the other is null, but is there another cleaner way to accomplish this?
Thanks,
Ben
Use coalesce to pick up the value from the other table in case the value exists in one table and not the other.
select coalesce(A.color,B.color) as color, count(*)
from A
full join B on a.color = B.color
group by 1
order by 1
I have a table containing order details. I would like to be able to select the average attribute for a certain item.
For example, select "item a", now find the average color of "item a". If there were 10 orders of "item a" and the colors ordered broke down as follows:
4 - black
2 - blue
2 - red
1 - orange
1 - white
I would like for it to return "black". Is there any such statement that could do that?
Also, would it then be possible to weigh the average, for example giving the last 3 orders of "item a" a weight of 2, instead of 1. So if the last 3 orders were all yellow, it would essentially count as 6?
You can group by on color, and then select the first row:
select color
from OrderLines
where ItemId = 'item a'
group by
color
order by
count(*) desc
limit 1
You could give some rows a higher weight with a subquery. This one gives the last 3 orders a higher weight:
select color
from (
select o1.color
, case when
(
select count(*)
from OrderLines o2
where o1.item = o2.item
and o1.OrderDt < o2.OrderDt
) < 3 then 2 else 1 end as weight
from OrderLines o1
)
where Item = 'item a'
group by
color
order by
sum(weight) desc
limit 1