MySQL Data from two tables: Adding column headings to output - mysql

I use following to get data from two tables:
SELECT p.id, p.title, p.event_date, a.name, p.location_id
FROM ixrsk_eb_events p
INNER JOIN ixrsk_eb_locations a on p.location_id = a.id
This works fine.
Now in addition, I want to have column headings.
On top of the results: "ID" (col p.id), "Title" (col p.title), "Date" (col p.event_date) and "Location" (col a.name).
And column p.location_id should not be displayed at all (no heading, no data).
How can I do this?

you can use aliases to change the names of the columns you show:
SELECT
p.id AS ID,
p.title AS Title,
p.event_date AS Date,
a.name AS Location
FROM ixrsk_eb_events p
INNER JOIN ixrsk_eb_locations a on p.location_id = a.id
and just leave out the columns you do not want to show up.

You are looking for aliasing the column/expressions. Refer this tutorial for further explanation: http://www.mysqltutorial.org/mysql-alias/
SELECT p.id AS ID,
p.title AS Title,
p.event_date AS Date,
a.name AS Location
-- removed p.location_id
FROM ixrsk_eb_events p
INNER JOIN ixrsk_eb_locations a on p.location_id = a.id
To skip a particular column, you simply need to remove that from the SELECT clause.

Related

Select rows with same id that have other data ( search )

I'm trying to build a search function but the current table structure troubles me.
So each row identifies a 'tag' association with an audio ID.
TABLE audio_tag_assoc example
I get the name of each tag id by joining the table tag_association.
TABLE tag_association example
Therefore I need to get all the audio ids that match two or even three tag names.
What I tried is the following but you can probably tell that it doesn't work. I would have later added a join in between those parentheses to change the IDs of the IN with strings.
SELECT *
FROM audio_tag_assoc a
JOIN tag_association b ON a.tag = b.id
WHERE a.audio = (SELECT *
FROM audio_tag_assoc
WHERE tag IN (2,3)
)
Initially I tried having b.name = 'Male' AND b.name = 'Film' but of course, that's not how mysql WHERE clause works.
Do :
SELECT
*
FROM
audio_tag_assoc
INNER JOIN
tag_association ON audio_tag_assoc.tag = tag_association.id
WHERE
audio_tag_assoc.id IN (SELECT
a.id
FROM audio_tag_assoc a
WHERE
a.tag IN (2,3)
GROUP BY
a.audio
HAVING COUNT(a.id) >= 2
);

How can I use a join to combine these two queries?

I have two tables: articles and modifications. I want users to easily be able to revert their article back to it's original state if they realize they shouldn't have modified it. Instead of using an extra query to find the id of the article's newest modification, I would like to use a join. So I want to get the information from the articles table and then join the modifications table to it to return the associated row. This is what I have now:
<?php
$query = "
SELECT
article_id, title, content
FROM articles
WHERE article_id = ".$article_id."
LIMIT 1";
$query_article = $this->db->query($query);
$article = $query_article->row_array();
$query_mod = "
SELECT
modification_id, article_id, title, content, date
FROM modifications
WHERE article_id = ".$article_id."
ORDER BY modification_id DESC
LIMIT 1";
$query_mod = $this->db->query($query);
if($query_mod->num_rows() > 0){
$mod = $query_mod->row_array();
$article_title = $mod['title'];
$article_content = $mod['content'];
} else {
$article_title = $article['title'];
$article_content = $article['content'];
}
How could I combine these two queries into one using a join?
SELECT
a.title, a.content, a.article_id
m.modification_id AS mod_id, m.title AS mod_title, m.content AS mod_content
FROM articles AS a
LEFT JOIN modifications AS m ON (...)
WHERE a.article_id = 1
LIMIT 1
Your skeletal attempt at a query is pretty much correct except for the empty ON clause, which merely needs to identify equality between article_id on the two tables. It is correct to use a LEFT JOIN since you need to return the article regardless of a match in modifications.
SELECT
a.title, a.content, a.article_id,
m.modification_id AS mod_id, m.title AS mod_title, m.content AS mod_content
FROM
articles AS a
LEFT JOIN modifications AS m ON a.article_id = m.article_id
WHERE a.article_id = 1
ORDER BY mod_id DESC LIMIT 1
However, your PHP logic shows that you are conditionally using the title,content from the modifications table if it is present. For that, you may use COALESCE() directly in the SQL to return the first non-null argument, so if the LEFT JOIN has no match, article will be used.
SELECT
-- COALESCE to prefer the modifications value if non-null
COALESCE(m.title,a.title) AS title,
COALESCE(m.content, a.content) AS content,
a.article_id,
m.modification_id AS mod_id
FROM
articles AS a
LEFT JOIN modifications AS m ON a.article_id = m.article_id
WHERE a.article_id = 1
ORDER BY mod_id DESC LIMIT 1
Here's a demonstration: http://sqlfiddle.com/#!2/1085c/1
Because you're only attempting to return details for one article_id, no subqueries are needed. This gets a little more complicated if you want to return the latest for multiple article_id, requiring a subquery join with a MAX() aggregate.
SELECT
COALESCE(m.title,a.title) AS title,
COALESCE(m.content, a.content) AS content,
a.article_id,
m.modification_id AS mod_id
FROM
articles AS a
-- Join articles against a subquery to get the most recent mod_id only
LEFT JOIN (
SELECT article_id, MAX(modification_id) AS mod_id
FROM modifications
GROUP BY article_id
) mm ON mm.article_id = a.article_id
-- and then join that mod_id against the rest of the modifications table
LEFT JOIN modifications m ON mm.mod_id = m.modification_id
WHERE article_id IN (<multiple criteria for article_id>)
http://sqlfiddle.com/#!2/14051/2

MySql LEFT JOIN within LEFT JOIN

I am trying to do the following MySql query for a search box. I am trying to return the "Album" info (Title etc) while including a thumbnail of the first image in that album. However, I have to look up two tables to get the image info. First, the photos_albums that contain all the images in that album, get the first image ID from that table, then look up that image info in the photos table. I believe the problem I am having, is that I need to tell the first LEFT JOIN to limit the query to 1, but I have had no luck doing this. I think I need to do a JOIN within a JOIN? Any help on this would be much appreciated.
SELECT albums.title, albums.title_url, photos.path, photos.medType, photos.vpath
FROM albums
LEFT JOIN photos_albums
ON photos_albums.album_id = albums.id
LEFT JOIN photos
ON photos_albums.photo_id = photos.id
WHERE albums.user = '$site_user'
AND (
albums.title LIKE '$keyword%'
OR albums.title LIKE '% $keyword%')
LIMIT 6
You can try something like this
SELECT a.title, a.title_url, q.path, q.medType, q.vpath
FROM albums a LEFT JOIN
(
SELECT pa.album_id, pa.photo_id, p.path, p.medType, p.vpath
FROM
(
SELECT album_id, MIN(photo_id) photo_id
FROM photos_albums
GROUP BY album_id
) pa JOIN photos p
ON pa.photo_id = p.id
) q
ON a.id = q.album_id
WHERE a.user = '$site_user'
AND (
a.title LIKE '$keyword%'
OR a.title LIKE '% $keyword%')
LIMIT 6

Select two table and order by date

i am trying to list out the latest update from two table doc_to_do and doc_bug_tracker below is my table structure
doc_to_do
doc_bug_tracker
and this is my current query :
$sth = $this->db->prepare('SELECT p.*,
dtd.projects_id as dtd_projects_id, dtd.content as dtd_content, dtd.date_modified as dtd_date_modified,
dbt.projects_id as dbt_projects_id, dbt.content as dbt_content, dbt.date_modified as dbt_date_modified
FROM `projects` p LEFT JOIN `doc_to_do` dtd ON p.id=dtd.projects_id
LEFT JOIN `doc_bug_tracker` dbt ON p.id=dbt.projects_id
where p.id="'.$project_id.'"');
so now how to order by date_modified either from table doc_to_do or doc_bug_tracker ?
To get only the latest date (as opposed to all dates, ordered descending) try this:
SELECT
p.id,
MAX(GREATEST(dtd.date_modified, dbt.date_modified)) AS MaxDate
FROM projects p
LEFT JOIN doc_to_do dtd ON p.id = dtd.projects_id
LEFT JOIN doc_bug_tracker dbt ON p.id = dbt.projects_id
WHERE p.id = <project_id>
GROUP BY p.id
If you need additional columns in your SELECT, be sure to include them in your GROUP BY.
This should work :
'SELECT x.* FROM
(
SELECT p.*,
dtd.projects_id as dtd_projects_id, dtd.content as dtd_content, dtd.date_modified as dtd_date_modified,
dbt.projects_id as dbt_projects_id, dbt.content as dbt_content, dbt.date_modified as dbt_date_modified
FROM `projects` p LEFT JOIN `doc_to_do` dtd ON p.id=dtd.projects_id
LEFT JOIN `doc_bug_tracker` dbt ON p.id=dbt.projects_id
where p.id="'.$project_id.'"
) x
ORDER BY x.date_modified ASC'

Select multiple tables

This is a part of my DB structure that I want to query:
The relations are these:
article.art_author - user.usr_id
article.art_id - tag_article.rel_art_id
tag_article.rel_tag_id - tag.tag_id
I want to select the articles that are written from selected users (by usr_id) OR the article that have the selected tags (by tag_id) in one query if possible.
I have tried this but does not give me the desired result:
SELECT * FROM
((article JOIN user on article.art_author = user.usr_id)
JOIN
tag_article on article.art_id = tag_article.rel_art_id)
JOIN
tag on tag_article.rel_tag_id = tag.tag_id
WHERE
article.art_lang = '$cur_lang'
$sql_in
ORDER BY
article.art_date desc
LIMIT $first_record, $range
select distinct a.art_id
from article a,
user u,
tag_article ta,
tag t
where a.art_author=u.user_id
and ta.rel_art_id = a.art_id
and ta.rel_tag_id = t.tag_id
and (u.usr_id in (<your selected users>) or t.tag_id in (<your selected tag>))
I wrote all joints so you can select all columns you want, but it can be done more rapidly if you just need article data :
select a.art_id
from article a,
tag_article ta
where a.art_id=ta.rel_art_id
and (a.art_author in (<your selected users>) or ta.rel_tag_id in (<your selected tags>))