This isn't as simple as the title. (What is an appropriate title?) I think the easiest way to describe my issue is with an example.
My goal is a list of what color balloon’s each child is missing.
Let’s assume table 1 contains the following data in 2 columns:
Child BalloonColor
Sally Yellow
Sally White
Sally Blue
Bob Red
Bob Green
Bob White
This is table 2, also 2 columns.
ColorCode Color
Y Yellow
W White
R Red
B Blue
G Green
P Pink
I need a write a result set that states what color balloon each child needs to have all colors.
Sally, R, Red
Sally, G, Green
Sally, P, Pink
Bob, Y, Yellow
Bob, B, Blue
Bob, P, Pink
My example is small, but assume I have a 1000 children in my table 1 and 75 colors in table 2. How can I check each child, one at a time, is my ultimate question? A Not in query will only yield "P, Pink", but you can see I need it at the child level, not table level.
I'm not a developer, but can write good SQL statements.
MS SQL Server 2008 R2.
Thanks in advance, Mike.
SELECT
SQ.child_name,
BC.balloon_color
FROM
(
SELECT DISTINCT
child_name
FROM
Child_Balloons
) SQ
CROSS JOIN Balloon_Colors BC
WHERE
NOT EXISTS (
SELECT *
FROM Child_Balloons CB
WHERE
CB.child_name = SQ.child_name AND
CB.balloon_color = BC.balloon_color
)
Related
Say I have a data table like this:
Name
Color
Food
John
Black
Pizza
John
Blue
Pasta
John
Blue
Fries
I ran this code to combine ID's 2 and 3 together, so that the value for the "Food" field will show "Pasta/Fries" This is the code that I ran on Amazon Redshift:
SELECT Name, Color, listagg(Food, '/') WITHIN GROUP (ORDER BY Food) as Food FROM data GROUP BY Name, Color ORDER BY Name, Color
It successfully produced the table that I want:
Name
Color
Food
John
Black
Pizza
John
Blue
Pasta/Fries
--
Now let's say the original data table was revised and now has an additional column for Race:
Name
Color
Food
Race
John
Black
Pizza
Asian
John
Blue
Pasta
White
John
Blue
Fries
NULL
The problem I now face is when I run the code stated above, but now including Race:
SELECT Name, Color, Race, listagg(Food, '/') WITHIN GROUP (ORDER BY Food) as Food FROM data GROUP BY Name, Color, Race ORDER BY Name, Color, Race
What happens is it won't aggregate the two rows (Pasta and Fries) anymore because the value for "Race" is different for both rows. How can I modify my code so that since the value of Race for Fries is NULL, I just want to return "White" i.e. I want my final table to look like:
Name
Color
Food
Race
John
Black
Pizza
Asian
John
Blue
Pasta/Fries
White
So I got this query and it's pulling from tables like this:
Plantation TABLE
PLANT ID, Color Description
1 Red
2 Green
3 Purple
Vegetable Table
VegetabkeID, PLANT ID, Feeldesc
199 1 Harsh
200 1 Sticky
201 2 Bitter
202 3 Bland
and now in my Query I join them using PLANT ID ( I Use a left join)
PLANT ID, Color Description, Feeldesc
1 Red Harsh
1 Red Sticky
2 Green Bitter
3 Purple Bland
So the problem is that in the Query you can see Red shows up twice! I can't have this, and
I'm not sure how to make the joins happen but stop reds from coming up twice.
It seems remotely possible that you're asking how do to group indication -- that is, showing a value which identifies or describes a group only on the first line of that group. In that case, you want to use the lag() window function.
Assuming setup of the schema and data is like this:
create table plant (plantId int not null primary key, color text not null);
create table vegetable (vegetableId int not null, plantId int not null,
Feeldesc text not null, primary key (vegetableId, plantId));
insert into plant values (1,'Red'),(2,'Green'),(3,'Purple');
insert into vegetable values (199,1,'Harsh'),(200,1,'Sticky'),
(201,2,'Bitter'),(202,3,'Bland');
The results you show (modulus column headings) could be obtained with this simple query:
select p.plantId, p.color, v.Feeldesc
from plant p left join vegetable v using (plantId)
order by plantId, vegetableId;
If you're looking to suppress display of the repeated information after the first line, this query will do it:
select
case when plantId = lag(plantId) over w then null
else plantId end as plantId,
case when p.color = lag(p.color) over w then null
else p.color end as color,
v.Feeldesc
from plant p left join vegetable v using (plantId)
window w as (partition by plantId order by vegetableId);
The results look like this:
plantid | color | feeldesc
---------+--------+----------
1 | Red | Harsh
| | Sticky
2 | Green | Bitter
3 | Purple | Bland
(4 rows)
I had to do something like the above just this week to produce a listing directly out of psql which was easy for the end user to read; otherwise it never would have occurred to me that you might be asking about this functionality. Hopefully this answers your question, although I might be completely off base.
Check array_agg function in the documentation it can be used something like this:
SELECT
v.plantId
,v.color
,array_to_string(array_agg(v.Feeldesc),', ')
FROM
vegetable
INNER JOIN plant USING (plantId)
GROUP BY
v.plantId
,v.color
or use
SELECT DISTINCT
v.plantId
,v.color
FROM
vegetable
INNER JOIN plant USING (plantId)
disclaimer: hand written, syntax errors expected :)
I want to implement graph coloring using databases.
There is a table that will store all the vertices (1,2,3...) and a table that stores the name of all colors(red,blue,green,etc..).
Now a want to create a coloring table with columns vertex and color which will take all possible combinations from the above tables and then check the constraints in each of those tables. Whichever table satisfies the constraints of graph coloring is a solution.
Now how to create tables for each combinations??
Guys please help. Stuck on it from a while...
An example instance:
vertex
1
2
3
Colors
red
blue
coloring
a)
1 red
2 blue
3 red
b)
1 red
2 red
3 blue
c)
1 blue
2 red
3 red
.
.
.
6 tables
I'm not sure I understand your question, so I'll make some assumptions. Assuming you have a table called Vertex, with the following rows:
1
2
3
... and a table called Color, with the following rows:
Red
Green
Blue
... you can generate a table of all possible combinations with a simple unconstrained join, like this:
SELECT *
INTO VertexColor
FROM Vertex, Color
The result will be a new table, with the following rows:
1, Red
1, Green
1, Blue
2, Red
2, Green
2, Blue
3, Red
3, Green
3, Blue
Happy to help further if this does not answer your question.
SELECT Vertices.vertex, Colors.Color from Vertices
CROSS JOIN Color from Colors
EDIT: Seeing the new comments: This doesn't sound like a problem that is well suited for SQL, mainly because your number of columns in your resultset is dependent on the number of rows in your vertices table. That's not something that is easy in SQL (you probably need a multistep process, using dynamic sql through sp_execute). Since the ordering of the colums carries significance, you can't return a resultset containing only each vertex - color pair either, because the order in which the rows are returned may vary. To me it sounds like a problem better handled outside the database engine. You can still use the above cross join to get a preliminary dataset, where you filter out some conditions you have on the set.
I have a table with the following sampled data:
Name Color
Alice Green
Bob Black
Chris Green
Chris Black
David Red
Peter Blue
Simon Blue
Simon Red
Simon Green
Ultimately, I want to reduce the table by consolidating the Color column like:
Name Color
Alice Green
Bob Black
Chris Green, Black
David Red
Peter Blue
Simon Blue, Red, Green
such that Name can become unique.
The table has no PRIMARY KEY, I got as far as creating a new column using ROW_NUMBER to distinguishing duplicates but don't know what to do next.:
rownumber Name Color
1 Alice Green
1 Bob Black
1 Chris Green
2 Chris Black
1 David Red
1 Peter Blue
1 Simon Blue
2 Simon Red
3 Simon Green
Don't do this. Instead, normalize your tables further to e.g. a Person, Preference and a Color table (where Preference, if that is the right name for the relation, has foreign keys to Person and Color). This way, you avoid the risks of inconsistencies (you can make Person names unique if you like, but you should make Color names unique).
EDITED: if you're getting this from a join query I'll assume the data is reasonably consistent, so normalization isn't an issue. Would it be possible to change the join query to GROUP on Name instead? Much cleaner than hacking around a result set, really!
I have adopted the approach here
with a table variable to hold the temporary result set to work(hack) from.
Sorted!
I have an addition SQL question, hopefully someone here can give me a hand.
I have the following mysql table:
ID Type Result
1 vinyl blue, red, green
1 leather purple, orange
2 leather yellow
and i am seeking the following output:
ID Row One Row Two
1 vinyl blue, red, green leather purple, orange
2 leather yellow
the thing is... type is not static... there are many different types and not all of them have the same ones. They need to follow in order.
Please post a show create table of your table. It's not clear what you mean in fact.
Maybe what you need is GROUP_CONCAT after all:
mysql> select ID, GROUP_CONCAT(type,' ',result) from test;
Let us know.