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
Related
I have a table with locations and there are duplicates because there are locations with same name that belongs to different counties.
+------+-----------+-----------
| ID | location | parent_id |
+------+-----------+------------+
| 1 | Country | 0 |
| 2 | County 1 | 1 |
| 3 | County 2 | 1 |
| 4 | A | 2 |
| 5 | B | 2 |
| 6 | C | 2 |
| 7 | A | 3 |
| 8 | E | 3 |
| 9 | B | 3 |
+---- -+-----------+------------+
I would like to create and insert in column duplicate for each duplicate ID value . The result should look like this: ( Would be better to add ID in duplicate column to all duplicates excepting the one with smallest ID)
| ID | location | parent_id | duplicate|
+------+-----------+------------+----------+
| 1 | Country | 0 | |
| 2 | County 1 | 1 | |
| 3 | County 2 | 1 | |
| 4 | A | 2 | 4 |
| 5 | B | 2 | 5 |
| 6 | C | 2 | |
| 7 | A | 3 | 7 |
| 8 | E | 3 | |
| 9 | B | 3 | 9 |
+---- -+-----------+------------+---------+
I use this to list the rows:
SELECT a.* FROM mytable a
JOIN (SELECT location, COUNT(*)
FROM mytable
GROUP BY location
HAVING count(*) > 1 ) b
ON a.location= b.location
ORDER BY a.location
It looks like a window count can do what you want:
select t.*,
case when count(*) over(partition by location) > 1 then id end duplicate
from mytable t
This requires MySQL 8.0. In earlier versions, an alternative is a correlated subquery:
select t.*,
case when (select count(*) from mytable t1 where t1.location = t.location) > 1 then id end duplicate
from mytable t
I have the following table in the maria database
i am looking for the following output as a view
I have tried different approaches but it is not working.
Use group_concat() to aggregate the ids and do a self join of the table:
select t.id, t.name,
group_concat(tt.id order by tt.id) repeated
from tablename t left join tablename tt
on tt.name = t.name and tt.id <> t.id
group by t.id, t.name
order by t.id
See the demo.
Results:
| id | name | repeated |
| --- | ----- | -------- |
| 1 | John | 4,8 |
| 2 | Smith | 3 |
| 3 | Smith | 2 |
| 4 | John | 1,8 |
| 5 | Anna | |
| 6 | David | 7 |
| 7 | David | 6 |
| 8 | John | 1,4 |
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
How to count base on the others table sum
I have this tables
CARDS
| ID | Name |
---------------------
| 1 | Nice |
| 2 | Wow |
| 3 | Lol |
| 4 | Ohyeah |
| 5 | Olala |
VOTES
ID | *card_id* | *user_id* | vote |
-------------------------------------------------
1 | 1 | 1 | -1 |
2 | 2 | 2 | -1 |
3 | 2 | 4 | 1 |
4 | 2 | 5 | 1 |
5 | 3 | 2 | 1 |
6 | 3 | 1 | 1 |
RESULT QUERY WHAT I WANT
| card_id | total_votes |
-------------------------------
| 1 | -1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 0 |
| 5 | 0 |
and this is what I've tried
SELECT c.*, COALESCE(SUM(v.vote),0) as vote_count
FROM cards c
LEFT JOIN votes v ON c.id = v.card_id
I don't where I mistake, please need help
You dont need subquery, just the group by
SQL Fiddle Demo
SELECT c.`ID`,
COALESCE(Sum(v.vote), 0) AS total_votes
FROM cards c
LEFT JOIN votes v
ON c.id = v.`card_id`
GROUP BY c.`ID`;
OUTPUT
| ID | total_votes |
|----|-------------|
| 1 | -1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 0 |
| 5 | 0 |
You should select all votes and group them by card_id. There u can simply use SUM function.
SELECT c.id, COALESCE(SUM(v.vote), 0)
FROM VOTES
LEFT JOIN c ON v.card_id = c.ID
GROUP BY v.card_id
Following query will do the trick
select c.id, sum(v.vote)
from cards c, votes v
where c.id = v.card_id
group by c.id
I have a complicated ordering issue in my query.
Raw, Unordered Data:
+------+--------+-----------+
| id | job_id | action_id |
+------+--------+-----------+
| 1 | 2 | 1 |
| 2 | 2 | 2 |
| 3 | 1 | 1 |
| 4 | 2 | 3 |
| 5 | 4 | 1 |
| 6 | 1 | 2 |
| 7 | 3 | 1 |
| 8 | 3 | 2 |
| 9 | 4 | 2 |
+------+--------+-----------+
Required Ordering:
+------+--------+-----------+
| id | job_id | action_id |
+------+--------+-----------+
| 7 | 3 | 1 |
| 8 | 3 | 2 |
| | | | * blank lines added for clarity,
| 5 | 4 | 1 | not desired in actual data
| 9 | 4 | 2 |
| | | |
| 3 | 1 | 1 |
| 6 | 1 | 2 |
| | | |
| 1 | 2 | 1 |
| 2 | 2 | 2 |
| 4 | 2 | 3 |
+------+--------+-----------+
The theory behind this ordering:
the largest id is the most recently added entry
the most recent id with action_id of 1
followed by the entries with ascending action_ids that have the same job_id
then the next most recent action_id of 1
ad infinitum
EDIT: I'm not able to add columns to the table in order to aid in sorting, as I've seen in some other solutions to ordering questions.
Any help is greatly appreciated!
My best shot is this:
SELECT * FROM tbl
ORDER BY FIND_IN_SET(job_id,
(SELECT GROUP_CONCAT(job_id ORDER BY ID DESC)
FROM tbl WHERE action_id = 1));
I didn't find a way to do it easily, What do you think of the following code :
select c.id, c.job_id, c.action_id
from (select a.id, a.job_id, a.action_id, min(b.id) as related_id
from myTable a
inner join myTable b
on a.job_id=b.job_id
group by a.job_id) c
group by c.id
order by c.related_id desc, c.action_id