I have 3 mysql tables (animal, category and animal_2_category). Every animal can have 0-n categories (for example fish, pet, insect, carnivore, "can fly", etc.).
Table "animal" (id, name)
1, dog
2, cat
3, bee
...
Table "categories" (id, name)
1, pet
2, insect
3, mammal
4, fish
5, can fly
...
Table "animal_2_category" (animal_id, category_id)
1, 1
1, 3
2, 1
2, 3
3, 2
3, 5
...
What I need now, is a list of all category combinations. The following query works:
SELECT CONCAT_WS("-", x.name, c.name)
FROM animal_2_category a2c1
JOIN animal_2_category a2c2 ON a2c1.animal_id = a2c2.animal_id
JOIN category c ON c.id = a2c2.category_id´
JOIN categories x
GROUP BY a2c2.category_id
This query wil return the following:
The problem with this is, that I get dublicate entries "pet-mammal" and "mammal-pet". How can I modify the query, to only get one of them, for example:
The || , operator is a nonstandard MySQL extension. As of MySQL 8.0. 17, this operator is deprecated; expect support for it to be removed in a future version of MySQL. Applications should be adjusted to use the standard SQL OR operator.
Query: SELECT *, CONCAT(FIRSTNAME, LASTNAME) AS FIRSTNAME FROM demo_table; Output: Here, we can see that FIRSTNAME and LASTNAME is concatenated but there is no space between them, If you want to add space between the FIRSTNAME and LASTNAME then add space(' ') in CONCAT() function.
To concatenate more than 2 fields with SQL, you can use CONCAT() or CONCAT_WS() function.
The CONCAT() function adds two or more expressions together.
You can also rewrite your query as
SELECT DISTINCT GREATEST(CONCAT_WS("-", x.name, c.name),CONCAT_WS("-", c.name, x.name)) col
FROM animal_2_category a2c1
JOIN animal_2_category a2c2 ON a2c1.animal_id = a2c2.animal_id
JOIN categories c ON c.id = a2c2.`category_id`
JOIN categories `x` ON a2c1.category_id = x.id
WHERE x.name <> c.name
DEMO
One way to avoid duplicate pairs is to ensure your pairs are always created in the same order. We can do that by assembling your pair in an if statement, which effectively sorts the two values for us. Then we just grab the distinct rows.
select distinct if(c1.name > c2.name, concat_ws('-', c1.name, c2.name), concat_ws('-', c2.name, c1.name)) pairing
from animal_2_category a1
inner join animal_2_category a2
on a1.animal_id = a2.animal_id
and a1.category_id <> a2.category_id
inner join categories c1
on a1.category_id = c1.id
inner join categories c2
on a2.category_id = c2.id;
Alternatively, just be more selective in the join criteria, so they only join in a particular order. This avoids the if, but we still need to grab the distinct values.
select distinct concat_ws('-', c1.name, c2.name) pairing
from animal_2_category a1
inner join animal_2_category a2
on a1.animal_id = a2.animal_id
and a1.category_id < a2.category_id
inner join categories c1
on a1.category_id = c1.id
inner join categories c2
on a2.category_id = c2.id;
demo here
Either way, the results are the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With