Clarification On MySQL Join Query - php

I am having some issues creating this JOIN query.
The table setup is as follows
| tags || tag_links || articles |
|________________||________________||________________|
| | | | | |
| id | | article_id | | id |
| tag_name | | tag_id | | |
There are 3 tables, and this is a many-to-many relationship.
The objective is to find all the tags associated with a given article
id.
The tags table contains all of the tags
The tag_links table contains the link between the articles and the
tags, where the tag_id is equal to the id in the tags table, and the
article_id is equal to the id in the article table
The articles table contains the id ( amongst other columns, but the
other columns are not important )
I am having a hard time because the article id is already provided. I don't think that this is even needed in the query, but I am at a loss right now. I am trying to grab all of the tag_id's that are associated with the article_id that I pass in, and then grab all of the tag_names from all of the tag_id's i just queried for.
Any help is greatly appreciated. Thanks!

This is a simple join you can use to get tag names for a given article id
select distinct t.* from tags t
join tag_links tl on(t.id = tl.tag_id)
where tl.article_id=#id <---- article id

Related

Applying filter using SQL Join

My website is a Q&A site like stackoverflow.com. When a user creates a question, he has the ability to tags it. Later, when he need to find all questions which belongs to a category, he can use the filter box which accepts tag names. Based on user entries, i will just refresh the job list.
My table design is like below
Table: Questions
id | QuestionTitle |Other details|
----------------------------------|-------------|
1 | Why is earth round? |
2 | How much is moon's diameter? |
Table: Tags
id | tagname
----------------
1 | planets
2 | earth
3 | moon
Table: AttachedTags
id | question_id | tag_id
-------------------------
1 | 1 |2
2 | 1 |1
3 | 2 |3
In the PHP/Controller i will get tag id's as user input's in the filter box.
What is the best method to fetch all those questions under a particular tag?
I have used the following query, but it is retrieving a job two times, because a job can have more than one category.
SELECT
Questions.id,
Questions.jobtitle,
AttachedTags.tag_id
FROM
Questions INNER JOIN
AttachedTags ON Questions.id = AttachedTags.question_id
WHERE
AttachedTags.tag_id IN (1,2)
Isn't it enough to add a distinct to filter out duplications and remove tag_id from the select?
SELECT DISTINCT
Questions.id,
Questions.jobtitle
FROM
Questions INNER JOIN
AttachedTags ON Questions.id = AttachedTags.question_id
WHERE
AttachedTags.tag_id IN (1,2)

When joining tables, date column is NULL on some etries

I am trying to migrate some custom CMS DB to Wordpress, and so far it's been a living hell.
I am using WP All import plugin, so I need a neat single .csv export that contains data from multiple tables from this custom cms database.
So, these are the columns from two tables that I want to join:
`eo_items`
| cat_id | identificator | create_date |
---------------------------------------------
| 1 | Title of the post | 1283786285 |
`eo_items_trans`
| item_id | lid | name | s_desc | l_desc |
---------------------------------------------------------
| 1 | 33 | Title of the post | excerpt | content |
Desired result should be:
| item_id | lid | name | s_desc | l_desc | cat_id | create_date |
--------------------------------------------------------------------------------
| 1 | 33 | Title of the post | excerpt | content | 1 | Some date |
Here is the script I am using:
SELECT DISTINCT
eo_items_trans.item_id,
eo_items_trans.lid,
eo_items.cat_id,
DATE_FORMAT( eo_items.create_date, '%d.%m.%Y' ) create_date,
eo_items_trans.s_desc,
eo_items_trans.l_desc,
eo_items_trans.name
FROM eo_items_trans
LEFT JOIN eo_items ON ( eo_items_trans.name = eo_items.identificator )
Trouble with this code is that in resulting table some date columns are NULL, and I don't know if the result is what I need because the table has around 2000 rows and I don't know how to cross check if category IDs are correctly populated.
This is the first time I am doing something like this with MySQL so I am really not sure if the procedure is right for what I am trying to achieve.
If you need any clarifications please ask.
EDIT:
eo_items table has some 300 rows more than eo_items_trans so there are some records there that don't have corresponding records in eo_items_trans. I am guessing this should be reflected in the query as well?
Since you're using a LEFT JOIN, NULLs will be returned for any rows of eo_items_trans that do not have entries in oe_items. This could mean the eo_items.identificator is empty, or doesn't exactly match the name (case sensitivity will apply).
You'll have to investigate and clean up the data for rows in eo_items_trans missing the expected row in eo_items.
You NULL results for date seem to come or from eo_items_trans records that have no corresponding entry in the eo_items table or from eo_items records where create_date is null.
You can easily crosscheck check by doing the following
Is there records in eo_items_trans that have no corresponding entries in eo_items:
SELECT DISTINCT eo_items_trans.name FROM eo_items_trans
where NOT EXISTS (
SELECT * FROM eo_items
where eo_items.identificator = eo_items_trans.name
)
If this yields one ore more rows, that will be the eo_items_trans.name records with no correspondent in eo_items. If this is you problem, the do a JOIN, not a LEFT join in your main query
As for empty dates in eo_items you might want to check like this
SELECT * from eo_items WHERE create_date IS NULL
If you find records here, this is where yout NULL values in the main query come from

How to get info from a child table using PDO in PHP with SQL?

How do I get information (via a parent table), from a child table that's using a foreign key that references the parent.
For example:
Table: user_list (parent)
-----------------------------
first_name | Last Name | ID |
-----------------------------
john | Appleseed | 4 |
| | |
Table: user_info: (child)
----------------------------------------------
email | password | userlist_ID |
----------------------------------------------
jappleseed#me.com | ******* | 4 |
Let's say I have John Appleseed's info stored in an array:
$johnsInfo;
How can I then retrieve John's email from the user_info table?
I'm trying this atm:
db->query("SELECT * FROM user_info WHERE userlist_ID = :ID", $johnsInfo);
Not sure if that's the right way of doing things though.
If this is a real example, you should just make the two tables into one table. Generally if tables have 1:1 correspondence, you should put them together (though, there are special cases when you shouldn't).
Anyway, you'd want to do something like:
SELECT ul.*, ui.* FROM user_list ul
LEFT JOIN user_info ui
ON ui.userlist_ID=ul.ID
WHERE ul.ID = :ID
There are different kinds of joins. Check out the MySQL documents (http://dev.mysql.com/doc/refman/5.0/en/join.html) or search for something like "database joins" to find out which one will end up working for you.
Here is the SQL you need
SELECT user_list.ID
,user_list.first_name
,user_list.last_name
,user_info.email
,user_info.password
FROM user_list
INNER JOIN user_info
ON user_list.ID = user_info.userlist_ID
WHERE user.ID = :ID

Reorder/reset column unique id in mysql

I do not know a lot of mysql. I have two tables on same server:
A.artists
id | artist_name
--------------------
8 | XXXX |
1 | YYYY |
5 | ZZZZ |
A.albums
id | artist_id | album_name
-----------------------------
1 | 5 | Album 1
2 | 1 | Album 2
3 | 8 | Album 3
I want to reorder the artist_id column, accordingly, at the same time I want to change A.artists's id column from reordered artist_id id.
Is it possible such a thing? How can I do that? Thanks!
First, you need to understand that tables in SQL are unordered. So, you cannot specify an ordering for the table. You can specify an ordering for a query.
My guess is that you want to join the two tables to get the name with the albums:
select al.*, ar.name
from albums al join
artists ar
on al.artist_id = ar.id
order by ar.name
The way your question is phrased is that you want to re-assign ids. Normally, this would not be necessary, since the ids exist only to uniquely identify rows. If you have a good reason for reassigning ids, then modify your question or ask a new question, including the reason.

MySQL inner join on two columns

I have two tables, books and authors. books has a author_id column and a secondary_author_id column (no books have more than two authors). I'm so far doing:
SELECT * FROM books
LEFT JOIN authors
ON books.author_id=authors.id
which is handling the join with the first author. I can't work out how I'd handle the secondary author though. Should I change my schema, or do I just need a bit of SQL help?
SELECT books.*, author1.*, author2.*
FROM books
LEFT JOIN author AS author1
ON author1.author_id = books.author_id
LEFT JOIN author AS author2
ON author2.author_id = books.secondary_author_id
In SQL, you can alias the tables by adding it after the table name. Just be careful, now you'll have duplicate columns, so instead of author1.* you will probably want to alias the results of both author1 and author2.
EDIT
Additional details -- Say you have your basic table (i'll include the details so if people want to test on their own they can):
CREATE DATABASE test;
USE test;
CREATE TABLE books
(
book_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(50),
author_id INT NOT NULL,
secondary_author_id INT
);
CREATE TABLE authors
(
author_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50)
);
INSERT INTO authors (author_id,name) VALUES (1,'Sue Z. Que'),(2,'John Doe'),(3,'Bob Smith');
INSERT INTO books (book_id,title,author_id,secondary_author_id) VALUES (1,'JOIN-ing Two Tables',1,2);
If you do the select I mention above, your result will be the following:
|----------------------- books TABLE -----------------------------|---- authors table -----|---- authors table ---|
+---------+---------------------+-----------+---------------------+-----------+------------+-----------+----------+
| book_id | title | author_id | secondary_author_id | author_id | name | author_id | name |
+---------+---------------------+-----------+---------------------+-----------+------------+-----------+----------+
| 1 | JOIN-ing Two Tables | 1 | 2 | 1 | Sue Z. Que | 2 | John Doe |
+---------+---------------------+-----------+---------------------+-----------+------------+-----------+----------+
(I've added the top header just for calrity's sake) you see you have two author_id's and two name's (as they are joins of the same table and same column names). BUT, if you alias the columns from the joins like so:
SELECT books.*, author1.name AS primary_author, author2.name AS secondary_author
FROM books
LEFT JOIN authors AS author1
ON author1.author_id = books.author_id
LEFT JOIN authors AS author2
ON author2.author_id = books.secondary_author_id;
You get a much cleaner result:
|----------------------- books TABLE -----------------------------| authors table -|- authors table --|
+---------+---------------------+-----------+---------------------+----------------+------------------+
| book_id | title | author_id | secondary_author_id | primary_author | secondary_author |
+---------+---------------------+-----------+---------------------+----------------+------------------+
| 1 | JOIN-ing Two Tables | 1 | 2 | Sue Z. Que | John Doe |
+---------+---------------------+-----------+---------------------+----------------+------------------+
SELECT books.* FROM books, authors.name, secondary_authors.name
LEFT JOIN authors
ON books.author_id=authors.id
LEFT JOIN authors as secondary_authors
ON books.secondary_author_id=secondary_authors.id
You need to rethink your design, because one day there will be a book with three authors, and the next day there will be a book with zero. (I've been there myself.)
Edit
As your comment says: yes, you need a books_authors table. As long as you have your indexes set up properly, it's not a big performance hit.
The most annoying part is that you're often going to want to string the authors together (one entry per book, concatenating all the authors into a single column). You'll probably end up creating a view for that.
just do another join on the secondary id

Categories