Combine multiple instances of entry into one, differences into array - sql

I have a table filled with cars, another table that has the car IDs and the feature IDs and another table with the feature IDs and feature names.
A car can have multiple features in that table. The result of the query is, that i get multiple instances of the same car, each having a different feature.
I would like to have only one instance of the car (by ID) and combine all features into one column (list or array). I could do it in code after the query but i would like to do it in a query instead.
Cars table Car property table Property table
ID Name Car_ID property_ID property_id Property_name
1 Audi 1 1 1 Aircon
2 BMW 1 2 2 Autopilot
3 Mercedes 2 1
3 2
Result is:
1 Audi Aircon
1 Audi Autopilot
2 BMW Autopilot
3 Mercedes None
Result should be:
1 Audi [Aircon, Autopilot]
2 BMW Autopilot
3 Mercedes None

This seems like a basic aggregation query with joins:
select c.name, group_concat(Property_name) as properties
from cars c left join
car_properties cp
on c.car_id = cp.car_id left join
properties p
on p.property_id = cp.property_id
group by c.name

Related

Find only complete match in join table

I have 3 tables, Pizza, Ingredient, and PizzaIngredients which is a join table between my first two tables.
Pizza
id
name
1
Margarita
2
Pepperoni
3
Vegetarian
Ingredient
id
name
1
Tomato
2
Pepperoni
3
Lettuce
PizzaIngredients
pizzaId
ingredientId
1
1
2
1
2
2
3
1
3
3
I have a list of ingredients, and I want to list all the pizza I can make with the ingredients I have. To be able to make a pizza, i need to have all its ingredients
If in my list of ingredients I have : [1], I want to return the pizza with id 1 since I can only make the Margarita pizza.
If in my list of ingredients I have : [1, 3], I want to return the pizza with id 1 and 3 since I can potentially make the Margarita or the Vegetarian.
What I've tried :
SELECT
pi.pizzaId
FROM
pizzaIngredients pi
WHERE
pi.ingredientsId NOT IN (
SELECT
DISTINCT pi2.ingredientsId
FROM
pizzaIngredients pi2
WHERE
pi2.ingredientsId NOT IN ('1')
)
But It also returns me pizza 2 and 3 which I dont want since I don't have all the ingredients. I use a postgresql database
try this :
SELECT pi.pizzaId
FROM pizzaIngredients pi
GROUP BY pi.pizzaId
HAVING array_agg(ingredientId) <# array [1,3]
dbfiddle

SQL query stops working if column repeats

I have a Datagridview like this:
Model day1 day2 day3
car 1 2 4
bike 2 3 5
ship 6 1 7
Then i save it in my database table like this:
date model qty id
day1 car 1 1
day2 car 2 2
day3 car 4 3
day1 bike 2 4
day2 bike 3 5
day3 bike 5 6
day1 ship 6 7
day2 ship 1 8
day3 ship 7 9
Then using this query:
Select Min(id) As id,model From table Group By model order by id
i get the list of models in the same order as i had them in the datagridview:
car
bike
ship
The problem comes when i save 2 models with the same name in the table and then execute my query,i expect to get this:
1 car
2 bike
3 ship
4 car
but instead i get this:
1 car
2 bike
3 ship
The second proble with the current design i have is, if somehow i manage to retrieve the list as in the datagrid view:
car
bike
ship
car
How im going to know which quantities are from the first "car" and which ones are from the last "car" so i can put them in the datagridview back again.
In resume, i want to show in the datagrid the info in the same order i had it when i save it, but i dont know if the problem is the design of my table or the query im doing.
Example:
Saving this in my table, and then doing a query to get the same info in the same format:
Model day1 day2 day3
car 1 2 4
bike 2 3 5
ship 6 1 7
car 1 2 4
The problem is your query, you are grouping by the model
This means it will get the minimum Id of all the cars of that model, so you have car twice, but it only shows once because it groups all records of model car and selects the minimum Id which will be 1
Try this:
Select Count(id) As ModelCount,model From table Group By model order by id
on your dataset with the four cars and you will find that it will return the following:
ModelCount | model
2 | car
1 | bike
1 | ship
Based on your description, this is a gaps-and-island problem, sort-of. Actually, it is a data representation problem. Why are you storing the data with a single id instead of a row id and column id?
Given the way you are sorting the data, you can subtract a sequence to identify groups. Then you can group by and get the original rows:
select model
from (select t.*, row_number() over (partition by model order by id) as seqnum
from t
) t
group by model, (id - seqnum)
order by min(id);
But let me emphasize that if you want row/column information, then that is what you should be storing in the database.

How to query in the same table, comparing the field count?

I need to query a table, in which the amount of a field should be equal to another, in the same table, for the same group.
This is my table:
ID BUYER CAR
1 1 Audi
2 1 Audi
3 1 BMW
4 1 BMW
5 2 Audi
6 2 Audi
7 2 BMW
8 2 BMW
9 2 BMW
I need to get if a buyer has bought the same amount of Audi than BMW, if not, those rows shouldn't be retrieved.
So, with this logic, the query should return all the rows for buyer 1 only , because he has bought 2 Audi and 2 BMW.
This will be the return table:
ID BUYER CAR
1 1 Audi
2 1 Audi
3 1 BMW
4 1 BMW
Hope you can help me.
This is the table:
http://sqlfiddle.com/#!3/853fa/3
Group by buyer and use the having clause to filter by BMW and Audi count. Then select all records of the buyers found.
select *
from mytable
where buyer in
(
select buyer
from mytable
group by buyer
having
sum(case when car = 'BMW' then 1 end) =
sum(case when car = 'Audi' then 1 end)
);

Can I create a composite foreign key in the following way?

I have a table A that contains the following columns
ID(PK) id_1
1 4
2 10
3 15
4 4
Now Im trying to create a table B with columns such that
ID(PK) Description id_1_a_id (composite foreign key(ID,id_1))
1 Apple (1,4)
2 Orange (2,10)
3 Banana (3,15)
4 dog (4,4)
5
Does this design make sense? Or is there a better way to do this? (SQL rookie)
Composite foreign keys are common and useful, but you don't have one. If you did, it would look like this.
ID(PK) Description A_id id_1
--
1 Apple 1 4
2 Orange 2 10
3 Banana 3 15
4 dog 4 4
But you wouldn't ordinarily do that, either. Ordinarily, you'd reference a unique set of columns in table A. The unique set of columns is just the single column A.ID. So your table would usually look like this.
ID(PK) Description A_id
--
1 Apple 1
2 Orange 2
3 Banana 3
4 dog 4
You wouldn't usually duplicate the values of A.id_1 in table B. If you need the values from A.id_1, write a query with a JOIN.
select B.ID, B.Description, A.ID, A.id_1
from B
inner join A on A.ID = B.A_id;
If the only unique constraint you have in your tables is on the ID numbers, you're doing it wrong. But that's a different question.

xzzIntersect groups of child rows

I have to get “suggested” groupings of records based off of existing data.
Table A has a composite key of Akey+Bkey. Table B has a primary key of Bkey.
Akey is generated from a SQL 2012 Sequence object and there is a one to many relationship between table A and table and Table B on Bkey.
The structure and sample data are listed below.
Table A
Akey Bkey ItemSequence
---- ---- ------------
1 1 1
1 5 2
1 7 3
2 7 1
3 2 1
3 3 2
Table B
Bkey GroupValue Data HashString
---- --------------- -------------- ----------
1 Ford Festiva AIR BAG HASH1
2 Ford Festiva RADIATOR CAP HASH2
3 Ford Festiva FUEL PUMP HASH3
4 Ford Mustang AIR FILTER HASH4
5 Ford Explorer AIR FILTER HASH5
6 Ford Edge RADIATOR CAP HASH2
7 Ford Edge FUEL PUMP HASH3
The query has to insert new groups into Table A that match existing sets of Bkeys where the HASH value matches in Table B. To depict the point I use the example of a car model. The hash values of the items within the model of the car could match exactly ( but they might not ). So if all items exist within of OVER the GroupValue then I want to insert a new set of records into Table A with the values where the exact matches were found within that group.
In the sample data you can see that AKey 3 has BKeys 2 and 3 and Bkeys 6 and 7 are a match so these 2 records would be inserted into Table A and a new sequence # generated for the AKey.
I am not sure I understand the part about the groups and GroupValue field.
According to what I understand, you want to insert into Table A any rows from Table B that match the HashString for the Bkey of each AKey and don't already exist in Table A?
If I understand correctly: for Akey1, row TableB.Bkey 7 should be added to Table A. Is that right?
If the logic is good, the following query should select those rows.
SELECT
a.Akey, a.Bkey, b3.*
FROM b
INNER JOIN a ON a.Bkey=b.Bkey
INNER JOIN b b2 ON b2.HashString=b.HashString and b2.Bkey=a.Bkey
INNER JOIN b b3 ON b3.HashString=b2.HashString AND b3.Bkey <> b.Bkey
WHERE a.Akey=3 --Comment this line for the full matches