MySQL with JOIN-Query - mysql

I want to connect differend Queries with each other, but I can't figure out a way how...
Table mcr_versions contains a list of plugin versions, I want to get the plugin_id of the last 10 updates:
SELECT plugin_id FROM mcr_versions ORDER BY time DESC LIMIT 10
At the next step I need to get the plugin from another table:
SELECT id, name, logo, rating FROM mcr_plugins WHERE id = plugin_id
Now I have a table containing plugin-category-relationships, only with plugin_id and cat_id, I want to get one cat_id for each plugin:
SELECT cat_id FROM mcr_plugin_cat WHERE plugin_id = id
The last table contains the name of the category:
SELECT name FROM mcr_categories WHERE id = cat_id
How can I connect these queries to one query?

select mcr_categories.name from mcr_versions
left join mcr_plugins on mcr_plugins.id = mcr_versions.plugin_id
left join plugin-category-relationships on plugin-category-relationships.plugin_id = mcr_versions.plugin_id
left join mcr_categories on mcr_categories.cat_id = plugin-category-relationships.cat_id
order by mcr_versions.time desc limit 10;
i may be wrong at some of the tables , but i beleive u got my point

Related

SQL: How to merge two complex queries into one, where the second one needs data from the first one

The goal is to load a list of chats where the user sending the request is a member in. Some of the chats are group chats (more than two members) and there I want to show the profile pictures from the users who wrote the last three messages.
The first query to load meta data like the title and the timestamp of the chat is:
SELECT Chat_Users.ID_Chat, Chats.title, Chats.lastMessageAt
FROM Chat_Users
JOIN Chats ON Chats.ID = Chat_Users.ID_Chat
GROUP BY Chat_Users.ID_Chat
HAVING COUNT(Chat_Users.ID_Chat) = 2
AND MAX(Chat_Users.ID_User = $userID) > 0
ORDER BY Chats.lastMessageAt DESC
LIMIT 20
The query to load the last three profile pictures from one of the chats loaded with the query above is:
SELECT GROUP_CONCAT(innerTable.profilePictures SEPARATOR ', ') AS 'ppUrls',
innerTable.ID_Chat
FROM
(
SELECT Chat_Users.ID_Chat, Users.profilePictureUrl AS profilePictures
FROM Users
JOIN Chat_Users ON Chat_Users.ID_User = Users.ID
JOIN Chat_Messages ON Chat_Messages.ID_Chat = Chat_Users.ID_Chat
WHERE Chat_Users.ID_Chat = $chatID
ORDER BY Chat_Messages.timestamp DESC
LIMIT 3
) innerTable
GROUP BY innerTable.ID_Chat
Both are working separately but I want to merge them together so I don't have to run the second query in a loop due to performance reasons. Unfortunately I have no idea how this can be achieved because the second query needs the $chatID, which it only gets from the first query.
So to clarify the desired result: The list with the profile picture urls (second query) should be just another column in the result of the first query.
I hope it is explained in a reasonably understandable way. Any help would be much appreciated.
Edit: Sample data from the affected tables:
Table "Chats":
Table "Chat_Users":
Table "Chat_Messages":
Table "Users":
This fufils the brief, however it requires a view because MySQL 5.x doesn't support the WITH clause.
It's long and cluncky and I've tried to shorten it but this is as good as I can get, hopefully someone will pop up in the comments with a way to make it shorter!
The view:
CREATE VIEW last_interaction AS
SELECT
id_chat,
id_user,
MAX(timestamp) AS timestamp
FROM chat_messages
GROUP BY id_user, id_chat
The query:
SELECT
Chat_Users.ID_Chat,
Chats.title,
Chats.lastMessageAt,
urls.pps AS profilePictureUrls
FROM Chat_Users
JOIN Chats ON Chats.ID = Chat_Users.ID_Chat
JOIN (
SELECT
lo.id_chat,
GROUP_CONCAT(users.profilePictureUrl) AS pps
FROM last_interaction lo
JOIN users ON users.id = lo.id_user
WHERE (
SELECT COUNT(*) -- the amount of more recent interactions
FROM last_interaction li
WHERE (li.timestamp = lo.timestamp AND li.id_user > lo.id_user)
) < 3
GROUP BY id_chat
) urls ON urls.id_chat = Chats.id
GROUP BY Chat_Users.ID_Chat
HAVING COUNT(Chat_Users.ID_Chat) > 2
AND MAX(Chat_Users.ID_User = $userID)
ORDER BY Chats.lastMessageAt DESC
LIMIT 20

SQL join and get another column

I'm trying to join two tables so I can easily order it, as one contains the names of items and the other doesn't. The tables:
user_games: UGID, UID, APPID, playtime
games_steam: APPID, name
my SQL so far:
SELECT user_games.*
FROM user_games
JOIN games_steam ON user_games.APPID = games_steam.APPID
WHERE user_games.UID = '76561197996836099'
GROUP BY user_games.APPID
ORDER BY games_steam.name ASC
LIMIT 0, 30
Just no idea how to get the name column into this aswell.
Is this what you are looking for?
SELECT user_games.*, games_steam.name
FROM user_games
JOIN games_steam
ON user_games.APPID = games_steam.APPID
WHERE user_games.UID = '76561197996836099'
GROUP BY user_games.APPID
ORDER BY games_steam.name ASC
LIMIT 0, 30

Dynamic SQL with embedded table

I have a query which does the job but instead of the trans_inventory (which is an ID of the location) I need to get the location_name.
This one is working to get the id
SELECT *
FROM {TABLE}
WHERE trans_product = 646
ORDER BY trans_date2 DESC Limit 1
But I wonder if I can do it this way, somehow embed the location table, I have tried but below doesn't work
SELECT *, site_location.location_name
FROM site_trans
cross join
(select *
From site_location)
site_location
WHERE trans_product=646 ORDER BY trans_date2 DESC Limit 1
sl.location in the JOIN must be the site_location location id field name - I used locastion_id but it might be likely id as well. I used LEFT JOIN to avoid missing site_trans in case there is no matching location id.
SELECT s.*, sl.location_name
FROM site_trans AS s
LEFT JOIN site_location AS sl ON sl.location_id = s.location_id
WHERE s.trans_product=646
ORDER BY s.trans_date2 DESC
Limit 1

Select one record after order by

i have a bunch of CD's that contain a bunch of artwork. I want to display a thumb image of each CD on a webpage and for that i need to pick just one image out of the many artwork that exist for that CD...
The query selects all of the artwork and i group by position and want to pick the first one. I don't no how to pick just the first image FOR EACH RECORD after i've order them...
The query is as following:
SELECT release_artwork.release_id, release_artwork.position, artwork.small_filename, artwork.small_width, artwork.small_height
FROM release_artwork
JOIN artwork ON artwork.artwork_id = release_artwork.artwork_id
ORDER BY release_artwork.position
I don't have a MySQL instance handy, but this should work - just define an inline table to hold the minimums, then join to that.
SELECT release_artwork.release_id, release_artwork.position, artwork.small_filename, artwork.small_width, artwork.small_height
FROM
release_artwork
inner JOIN artwork ON artwork.artwork_id = release_artwork.artwork_id
inner join
(
SELECT
ra.release_id as release_id
,min(ra.position) as rap
FROM
release_artwork ra
group by
ra.release_id
) mins
on mins.release_id = release_artwork.release_id
and mins.rap = release_artwork.position
ORDER BY
release_artwork.release_id
In this case you can use LIMIT 1, to limit the results you retrieve to just the first one.
SELECT release_artwork.release_id, release_artwork.position, artwork.small_filename, artwork.small_width, artwork.small_height
FROM release_artwork
JOIN artwork ON artwork.artwork_id = release_artwork.artwork_id
ORDER BY release_artwork.position LIMIT 1
Adding the LIMIT 1 at the end will limit it to a single result.

mysql limiting join

I've done a few searches on this subject but non of the solutions seem to work so perhaps my requirement is slightly different.
Basically I have a "content" table and a "file_screenshots" table. Each row in the "file_screenshots" table has a "screenshot_content_id" column. I want to select from the "content" table, join the "file_screenshots" table but only select a maximum of 5 screenshots for any single piece of content.
If this isn't possible i'm happy to use two queries, but again i'm not sure how to limit the results to only receiving 5 screenshots per piece of content.
Here is an example query:
SELECT * FROM content
LEFT JOIN file_screenshots
ON file_screenshots.screenshot_content_id = content.content_id
WHERE content_type_id = 4
Assuming you have some sort of unique id column in your file_screenshots table, this should work for you:
SELECT
c.*,
fs.*
FROM
content c
JOIN
file_screenshots fs
ON (fs.screenshot_content_id = c.content_id)
LEFT JOIN
file_screenshots fs2
ON (fs2.screenshot_content_id = c.content_id AND fs2.id < fs.id)
GROUP BY
fs.id
HAVING
COUNT(*) < 5
ORDER BY c.content_id, fs.id
I've named the id column id. Rename it if neccessary.
If you want the 5 screenshots with the highest id, reverse the fs2.id vs. fs.id comparison.
ON (fs2.screenshot_content_id = c.content_id AND fs2.id > fs.id)