I have two tables related via id.
books:
book_id | book_name | year | publisher | slug
chapters:
chapter_id | book_id | chapter_name
Now when I query the database to find all the chapters related to a book like this:
SELECT book_name, chapter_name FROM ci_books, ci_chapters WHERE ci_books.book_id = ci_chapters.book_id AND slug = 'twelvers-dawn';
I get:
**book_name | chapter_name**
twelvers | Rising Sun
twelvers | Slow Down
twelvers | Masochist
I get the name of the book repeating with each chapter, how can I a stop the name from repeating so that only the name shows once and all the chapters are displayed?
You could use GROUP_CONCAT() like:
SELECT book_name, GROUP_CONCAT(chapter_name) as ChapterNames
FROM ci_books, ci_chapters
WHERE ci_books.book_id = ci_chapters.book_id AND slug = 'twelvers-dawn'
GROUP BY book_name;
See resource here
Use GROUP_CONCAT() with GROUP_BY
SELECT book_name, GROUP_CONCAT(chapter_name) AS chapter_names
FROM ci_books, ci_chapters
WHERE ci_books.book_id = ci_chapters.book_id AND slug = 'twelvers-dawn'
GROUP BY book_name;
Related
I have one table that contains knowledge article information in our knowledge base.
For simplicity, it contains the following columns:
articleID, title, knowledge_base, state, article_content
The state is the workflow state of the article, of which I only care about the published version and article content is the html for the articles.
We are removing knowledge_base2, but there are articles in knowledge_base1 that link to those articles and I need to find and remove those links.
The links contain the articleID of the article, so I thought this would be easy.
I want to search the article_content column for any reference to the articleIDs of knowledge_base2. I used this code:
/* Any knowledge_base1 articles that link to an article in knowledge_base2. */
Select a.articleID, a.title
FROM table1 a
Join (SELECT articleID
From table1 b
Where state = 'Published'
AND knowledge_base LIKE 'Knowledge_base2') b
ON a.articleID = b.articleID
WHERE a.knowledge_base = 'Knowledge_base1'
AND a.state = 'Published'
AND a.`article_content` LIKE concat('%',b.articleID,'%')
ORDER BY a.articleID
When I run this I get no results but no errors. I know there are links in Knowledge_base1that reference those article IDs in Knowledge_base2 so there should be plenty of results. I assume this line is where I am wrong: "AND a.article_content LIKE concat('%',b.number,'%')"
Is there a better way to write this? Note, I have read only permissions to this database, and am not able to use local temp tables.
An example of the data in the table would look like this:
| articleID | title | knowledge_base | state | article_content |
+-----------+------------------------+-----------------+-----------+-------------
| KB0001 | How to fix a widget | knowledge_base1 | Published | http://sp?id=kb_article_view&sysparm_article=KB0002 |
| KB0002 | How to make a sandwich | knowledge_base2 | Published | Random HTML content |
| KB0003 | How to buy a car | knowledge_base1 | outdated | http://sp?id=kb_article_view&sysparm_article=KB0004 |
| KB0004 | House FAQs | knowledge_base2 | Published | Random HTML content |
+-----------+------------------------+-----------------+-----------+-------------
Final comment:
After much more research and testing This was what I found that appeared to give me the answer I needed:
Select a.articleID, a.title
FROM table1 a
Join (SELECT articleID
From table1 b
WHERE knowledge_base LIKE 'Knowledge_base2') b
ON a.article_content LIKE concat('%',b.articleID,'%')
WHERE a.knowledge_base = 'Knowledge_base1'
AND a.state = 'Published'
ORDER BY a.articleID
I have 3 tables (candidates, candidate_notes and candidate_events)
CANDIDATES | CANDIDATE_NOTES | CANDIDATE_EVENTS
id | id | id
name | candidate_event_id | type
surname | candidate_id
city | note
...
One candidate can have many notes.
One note has one kind of event.
I would like to obtain all the candidates that have notes of kind of event 1 but only that.
For example, if the candidate 1 have 5 notes, one of type 1, other 3 of type 3 and another one of type 6, I don't want to see it in the results.
Can someone help me with this query?
Thanks
One method uses group by and having:
select cn.candidate_id
from candidate_notes cn join
candidate_events e
on cn.candidate_event_id = e.candidate_event_id
group by cn.candidate_id
having min(type) = 1 and min(type) = max(type);
I have a table "story" as follows:
+++++++++++++++++++++++++++++++++++++++++++
| id | keywords |
+++++++++++++++++++++++++++++++++++++++++++
| 1 | romance,movie,drama |
| 2 | newmovie,horor,comedy |
| 3 | movie,scifi |
| 4 | newmovie,romance,drama,asia |
| 5 | kids,movie |
+++++++++++++++++++++++++++++++++++++++++++
I try a query to search 'movie' in keywords field as below:
SELECT id FROM story WHERE keywords LIKE '%movie%'
and the result is
1,2,3,4,5
but in this case I wanted the result is 1,3,5 (field value with newmovie not include). Can someone help me how the query to do it?
Thank you for your help..
You want to use find_in_set like this:
SELECT id FROM story WHERE find_in_set('movie', keywords) > 0;
Though you should really consider normalizing your table structure.
In this case, you could've stored one single keyword in one row, then the query would be simply like:
select id from story where keyword = 'movie';
and that would've been the end of it. No heavy string functions needed.
You could have structure like this:
keywords(id, name);
story(story_id,. . ., keyword_id);
then, you could simply join the two like this:
select s.*
from story s
inner join keywords k on s.keyword_id = k.id
where k.name = 'movie';
Your problem is that "newmovie" can be found by "%movie%" you need only search "movie".
I have two tables, "records", and "info".
The "records" table looks like:
mysql> SELECT * FROM records WHERE num = '7';
+-----+--------+----+------+-----+-----+------------+-----------+----------+---------------------+
| id | city | st | type | num | val | startdate | status | comments | updated |
+-----+--------+----+------+-----+-----+------------+-----------+----------+---------------------+
| 124 | Encino | CA | AAA | 7 | 1 | 1993-09-01 | allocated | | 2014-02-26 08:16:07 |
+-----+--------+----+------+-----+-----+------------+-----------+----------+---------------------+
and so on. Think of the "num" field in this table as a Company ID.
The "info" table contains information about certain companies, and uses that company id as a unique identifier. Not all companies listed in "records" will be in "info". An example of the "info" table:
mysql> SELECT * FROM info LIMIT 2;
+-----+-------+--------------------------+---------------------+
| org | name | description | updated |
+-----+-------+--------------------------+---------------------+
| 0 | ACME | | 2014-02-19 10:35:39 |
| 1 | AT&T | Some Phone Company, Inc. | 2014-02-18 15:29:50 |
+-----+-------+--------------------------+---------------------+
So "org" here will match "num" in the first table.
I want to be able to run a query that returns, on one line, everything but 'id', 'type' and 'val' from the 1st table, and IF APPLICABLE, the 'name' and 'description' from the 2nd table.
I can achieve what I want using this query:
SELECT city,st,num,startdate,status,comments,updated, \
( SELECT name FROM info WHERE org = '7') AS name, \
( SELECT description FROM info WHERE org = '7') AS description \
FROM records WHERE num = '7'
But I see at least two problems with it:
It seems inefficient to run two subqueries
When there is no record in "info", NULL is printed for the name and
description. I would like to print some string instead.
To address the first problem, I tried to return an array. But when no corresponding record exists in the "info" table, then I get nothing, not even the valid info from the "records" table. Here's my array query:
SELECT city,st,num,startdate,status,comments,updated,asinfo.name AS name,asinfo.description AS description \
FROM records, \
( SELECT name,description FROM info WHERE org = '7') AS asinfo \
WHERE num = '7'
This query works fine if a given company id exists in both tables.
To address the second problem, I tried various incantations of IFNULL and coalesce, to no avail.
I'd appreciate any insight.
Thanks.
Apply LEFT JOIN syntax:
SELECT
r.city,
r.st,
r.num,
r.startdate,
r.status,
r.comments,
r.updated,
IF(d.name IS NULL, 'Default', d.name) AS name,
IF(d.description IS NULL, 'Default', d.description) AS description
FROM
records AS r
LEFT JOIN info AS d ON r.num=d.org
WHERE
r.num='7'
that will work such way: LEFT JOIN looks into first table, and, if there are no corresponding records in second, it applies NULL. So you'll discover that with IF (or IFNULL) and do substitution of default string.
Use a LEFT JOIN to get null values when there's no matching row in the info table.
SELECT city,st,num,startdate,status,comments,updated,
IFNULL(name, 'Default Name') name,
IFNULL(description, 'Default Description') description
FROM records r
LEFT JOIN info i ON r.num = i.org
WHERE r.num = 7
It sounds like a simple LEFT JOIN from record to info will do the trick.
LEFT JOIN rather than JOIN in order to ensure you ALWAYS get all rows from the record table, and then the corresponding data in info table if a xref exists for that ID.
Whether using your sub-queries or using joins, if you always want to see all rows in record table, then you will always get NULLs corresponding to the info table where no xref exists. The only way to avoid that is to run some code that calls everything from record, and then iterates over the results to query info, to conditionally add to the record data.
I apologise in advance if this might seem simple as my assignment needs to be passed in 3 hours time and I don't have enough time to do some further research as I have another pending assignment to be submitted tonight. I only know the basic MYSQL commands and not these types. Please help.
Say that I have two tables:
________________ _________________
| customers | | agents |
|________________| |_________________|
|(pk)customer id | |(pk) agent_id |
|(fk) agent_id | | first_name |
| first_name | | last_name |
| last_name | | address |
|________________| |_________________|
Basically I would just like to know how to query something like: (in incorrect terms)
SELECT * FROM customers WHERE agent_id = '(agent_id of Michael Smith from the AGENTS table)'
obviously I only have the agent_id of the agent and i can directly call it if i know what the agents name is based on the id like:
SELECT * FROM customers WHERE agent_id = '4'
but how can i query it by submitting the agent first name and last name as parameter?
(first name and last name because agents can have the same names, or even same last names)
Remember your foreign key does not help you building the query, you have to tell the database what you want in the query (however, a foreign key can help data spread across tables more consistent).
You can use a JOIN here.
You can implement it like this:
SELECT *
FROM customers C
INNER JOIN agents A ON C.agent_id = A.agent_id
WHERE A.last_name = 'Smith'
AND A.first_name = 'Michael';
You can do it without a join as well.
select *
from customers
where customers.agent_id in (
select agents.agent_id
from agents
where agents.first_name = 'Michael' and agents.last_name = 'Smith'
);