Select rows from table by id of a left join table - mysql

I have 3 tables:
+-------------+ +-------------+ +-------------+
| hotel | | hot_cat | | category |
+------+------+ +------+------+ +-------------+
| id | name | | hid | cid | | id | name |
+------+------+ +------+------+ +-------------+
| 1 | X | | 1 | 1 | | 1 | cat1 |
+------+------+ +------+------+ +-------------+
| 2 | Y | | 1 | 2 | | 2 | cat2 |
+------+------+ +------+------+ +-------------+
| 3 | Z | | 2 | 2 | | 3 | cat3 |
+------+------+ +------+------+ +-------------+
| 2 | 3 | | 4 | cat4 |
+------+------+ +-------------+
| 2 | 4 |
+------+------+
I want to select hotels where category is some value, but with all other categories assigned to this hotel. I have this query:
SELECT hot.*,GROUP_CONCAT(cat.name SEPARATOR '<br>') AS cats
FROM hotel hot
LEFT JOIN hot_cat hc ON hc.hid = hot.id
LEFT JOIN category cat ON cat.id = hc.cid
WHERE cat.id = 2
GROUP BY hot.id
So I get this:
+------+------+-------------------------+
| id | name | cats |
+------+------+-------------------------+
| 1 | X | 'cat2' |
+------+------+-------------------------+
| 2 | Y | 'cat2' |
+------+------+-------------------------+
What I want to achieve:
+------+------+-------------------------+
| id | name | cats |
+------+------+-------------------------+
| 1 | X | 'cat1<br>cat2' |
+------+------+-------------------------+
| 2 | Y | 'cat2<br>cat3<br>cat4' |
+------+------+-------------------------+
I also want it to work without the where clause and get hotels without category assigned:
+------+------+-------------------------+
| id | name | cats |
+------+------+-------------------------+
| 1 | X | 'cat1<br>cat2' |
+------+------+-------------------------+
| 2 | Y | 'cat2<br>cat3<br>cat4' |
+------+------+-------------------------+
| 3 | Z | '' |
+------+------+-------------------------+

Start your query at the hot_cat table, and then join into hotel. It's one extra jump through the tables, but it solves the problem.
SELECT hot.*,GROUP_CONCAT(cat.name SEPARATOR '<br>') AS cats
FROM hot_cat hc1
LEFT JOIN hotel hot ON hc1.hid = hot.id
LEFT JOIN hot_cat hc ON hc.hid = hot.id
LEFT JOIN category cat ON cat.id = hc.cid
WHERE hc1.id = 2
GROUP BY hot.id
If, instead, you don't need the WHERE then you can just use your existing query without the WHERE clause.

Related

Select products from tag group or other which are not in group

How select products which has tag red in tag_group color or product which does NOT have tag_group color? Expected result is on bottom.
SQL Fiddle: http://sqlfiddle.com/#!9/2caf6a/1
SELECT product.name
FROM product
INNER JOIN product_tag ON product.id = product_tag.product_id
INNER JOIN tag ON product_tag.tag_id = tag.id
INNER JOIN tag_group ON tag.tag_group_id = tag_group.id
WHERE (tag_group.name = 'color' AND tag.name = 'red') OR ...
What I tried
... tag_group.name != 'color'
or this
... product_tag.tag_id NOT IN (1,2,3)
but its return ruby, crystal, emerald because
Schema
Data
Product
+---------------+
| id | name |
+---------------+
| 1 | ruby |
| 2 | emerald |
| 3 | sapphire |
| 3 | crystal |
+---------------+
product_tag
+------------+--------+
| product_id | tag_id |
+------------+--------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 2 | 4 |
+------------+--------+
tag
+----+-------+--------------+
| id | name | tag_group_id |
+----+-------+--------------+
| 1 | red | 1 |
| 2 | green | 1 |
| 3 | blue | 1 |
| 4 | new | 2 |
+----+-------+--------------+
tag_group
+----+--------+
| id | name |
+----+--------+
| 1 | color |
| 2 | ribbon |
+----+--------+
expected result:
+---------+
| name |
+---------+
| ruby |
| crystal |
+---------+

How to make a selection from two tables?

I have table 'articles'
+-------------+
| articles |
+----+--------+
| id | title |
+----+--------+
| 1 | title1 |
+----+--------+
| 2 | title2 |
+----+--------+
| 3 | title3 |
+----+--------+
table 'catalogue'
+---------------------+
| catalogue |
+----+--------+-------+
| id | group | name |
+----+--------+-------+
| 1 | group1 | name1 |
+----+--------+-------+
| 2 | group1 | name2 |
+----+--------+-------+
| 3 | group2 | name3 |
+----+--------+-------+
| 4 | group2 | name4 |
+----+--------+-------+
binding table 'bindTable'
+------------+--------------+-------+
| bindTable |
+------------+--------------+-------+
| id_article | id_catalogue | value |
+------------+--------------+-------+
| 1 | 2 | 1 |
+------------+--------------+-------+
| 1 | 3 | 4 |
+------------+--------------+-------+
| 3 | 1 | 2 |
+------------+--------------+-------+
| 3 | 3 | 1 |
+------------+--------------+-------+
| 3 | 4 | 3 |
+------------+--------------+-------+
and i need to get result as in table 'result', where i can get pairs "catalogue_name : value" for selected item from table 'article'
+-----------------------------------------------------+
| result |
+------------+---------------+----------------+-------+
| article_id | article_title | catalogue_name | value |
+------------+---------------+----------------+-------+
| 1 | title1 | group1_name2, | 1 |
| | | group2_name3 | 4 |
+------------+---------------+----------------+-------+
| 3 | title3 | group1_name1, | 2 |
| | | group2_name3, | 1 |
| | | group2_name4 | 3 |
+------------+---------------+----------------+-------+
Can anyone tell me a query string with one DB query? Thank you for attention.
My vision:
SELECT b.id_article, a.title, c.group, c.name, b.value
FROM bindTable b
JOIN articles a ON a.id = b.id_articles
JOIN catalogue c ON c.id = b.id_catalogue
WHERE b.id_article = 1
but i need one row with pairs c.name&b.value for one a.id
A select with inner join
select a.article_id, a.article_title, b.catalogue_name, b.value
from bindTable as c
inner join articles as a on a.id = c. article_id
inner join catalogues as b on c. id_catalogue = b.id
This should do it.
SELECT articles.id AS article_id,
articles.title AS article_title,
CONCAT_WS('_', catalogue.group, catalogue.name) AS catalogue_name,
bindTable.value AS value
FROM bindTable
INNER JOIN articles ON bindTable.id_article = articles.id
INNER JOIN catalogue ON bindTable.id_catalogue = catalogue.id

I need help for many to many relation query

I have working on database for dictionary project. I have to store a word and meaning with many to many relationship.
Below I have mentioned the sample with my table structure. I hope the table structure is right, but I don't know how to select all meanings for single word while user searching.
And also I have to write a query to select all word and synonyms linked to a single meaning. And also I have to write a query to select all meaning and synonyms linked to a single word.
word_table
+----+------+
| id | word |
+----+------+
| 1 | A |
| 2 | B |
| 3 | C |
+----+------+
meaning_table
+----+--------+
| id | meaning|
+----+--------+
| 1 | X |
| 2 | Y |
| 3 | Z |
+----+--------+
word_meaning_table
+---------+-----------+
| word_id | meaning_id|
+---------+-----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 3 |
| 3 | 2 |
| 3 | 3 |
+---------+-----------+
synonyms_table
+----+--------+
| id | synonys|
+----+--------+
| 1 | aa |
| 2 | bb |
| 3 | cc |
+----+--------+
word_synonyms_table
+---------+-----------+
| word_id | synonym_id|
+---------+-----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
+---------+-----------+
Expected output should be like this.
If user searching for a word "A" in word table the result should be
Result for word "A"
+----+----------+---------+
| word| meaning | synonys |
+----+----------+---------+
| A | X | aa |
| A | Y | bb |
| A | Z | cc |
+----+----------+---------+
You just need many joins:
SELECT w.word,m.meaning,s.synonys
FROM word_table w
INNER JOIN word_meaning_table wm
ON(w.id = wm.word_id)
INNER JOIN meaning_table m
ON(wm.meaning_id = m.id)
INNER JOIN word_synonyms_table ws
ON(w.id = ws.word_id)
INNER JOIN synonyms_table s
ON(ws.synonym_id = s.id)
Let me reffer you to this document that explain all about join syntax's.

MYSQL add row and count from diffrent table

I have mysql database with two tables.
First (information)
+---------+------+----------+
| species | sex | user |
+---------+------+----------+
| bird | NULL | 1 |
| bird | f | 1 |
| cat | f | 1 |
| cat | m | 1 |
| dog | f | 1 |
| dog | m | 2 |
| hamster | f | 2 |
| snake | m | 1 |
+---------+------+----------+
Second (users)
+--------+-----+
| user | id |
+--------+-----+
| amy | 1 |
| dav | 2 |
| mot | 3 |
| mmm | 4 |
| aaw | 5 |
| dsa | 6 |
+--------+-----+
I want to count and show values from table "information" for each user row on table "users"
Like this
+---------+------+----------+
| user | id | count |
+---------+------+----------+
| amy | 1 | 6 |
| dav | 2 | 2 |
| mot | 3 | 0 |
| mmm | 4 | 0 |
| aaw | 5 | 0 |
| dsa | 6 | 0 |
+---------+------+----------+
How can I do this query?
select users.user, users.id, count (species.name)
from users left join species
on users.id = species.user
group by users.user, users.id
order by count (species.name) desc
Isn't it something like:
select u.user, u.id, count(i.user)
from user u
inner join information i on i.user = u.id
group by u.user, u.id

Don't know how to merge two MySQL tables

I'm new in SQL queries. I have a problem with the query.
I have table books:
+----+-------+--------+-----------+
| id | title | author | publisher |
+----+-------+--------+-----------+
| 1 | Book1 | 1 | 1 |
| 2 | Book2 | 1 | 2 |
| 3 | Book3 | 2 | 1 |
| 4 | Book4 | 2 | 2 |
| 5 | Book5 | 2 | 3 |
+----+-------+--------+-----------+
And I'm have another table, which contains copies of books with given book_id.
+----+---------+
| id | book_id |
+----+---------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
| 6 | 3 |
| 7 | 4 |
| 8 | 4 |
| 9 | 5 |
+----+---------+
All I need is to merge these two tables into one to have table sorted by amount of book copies.
I found solution to get table sorted by amount of book copies:
select book_copies.book_id, count(*) total_count
from book_copies
group by book_id
having count(*) > 0
order by count(*) desc;
+---------+-------------+
| book_id | total_count |
+---------+-------------+
| 1 | 3 |
| 2 | 2 |
| 4 | 2 |
| 3 | 1 |
| 5 | 1 |
+---------+-------------+
Now I don't know how to merge them.
I've tried like this:
select books.title from books
left join
(select book_copies.book_id, count(*) total_count
from book_copies
group by book_id
having count(*) > 0
order by count(*) desc)
as total_table on books.id = total_table.book_id;
But all I get was this:
+-------+
| title |
+-------+
| Book1 |
| Book2 |
| Book3 |
| Book4 |
| Book5 |
+-------+
Could you help me please?
EDIT: by merging I meant smth like this:
+-------+--------+-----------+-----+
| title | author | publisher | tot |
+-------+--------+-----------+-----+
| Book1 | 1 | 1 | 3 |
| Book2 | 1 | 2 | 2 |
| Book4 | 2 | 2 | 2 |
| Book3 | 2 | 1 | 1 |
+-------+--------+-----------+-----+
Many thanks to #Marco for the answer!
Dmitriy
I think you could try:
SELECT b.title, b.author, b.publisher, COUNT(bc.book_id) AS tot
FROM books b LEFT JOIN book_copies bc
ON b.id = bc.book_id
GROUP BY b.id
EDITED:
If you want sort, you can try
SELECT * FROM
(SELECT b.title, b.author, b.publisher, COUNT(bc.book_id) AS tot
FROM books b LEFT JOIN book_copies bc
ON b.id = bc.book_id
GROUP BY b.id) g
ORDER BY g.tot DESC