I've been trying to get a query which would allow me to put all music genres of an event (Link table) in a single row but I have been quite unsuccessful so far; it constantly returns 2 rows with the same information about the event in each but changing the music genre entries at the LEFT JOIN. Here's my query:
SELECT
events.*
, music_genres_link.*
FROM events
LEFT JOIN music_genres_link
ON events.id = music_genres_link.event_id
WHERE events.id=1
ORDER BY date DESC
And here's what it returns:
How do I get these two rows together in a single one? I need both the genre_title and genre_id columns.
I'd like to get the whole event row and left join all the music genres found on the link table to the left of the result, as such:
[event result] [music_genre_1 (id, title)] [music_genre_2 (id, title)] etc
I suspect you just want group_concat():
SELECT e.*, GROUP_CONCAT(mgl.genre_title) as genres
FROM events e LEFT JOIN
music_genres_link mgl
ON e.id = mgl.event_id
WHERE e.id = 1
GROUP BY e.id;
This assumes that you want the genre_title only. If you want the genre_id, then you can add another column.
It seems that you have 2 rows that match the join in music_genres_link. You can see that from the two 'gender_id' values - 5 and 295.
Ok now that you have edited your question, you want something that is not typical for SQL. You can achieve that with PIVOT but you dont have limit for the amount of genres and i wouldn't recommend it. You need to rethink your tables and what you want to achieve.
Related
I want to write out the number of times a car has been rented and I just cant get it to work, I have two tables. one is called vehicle and the other rental.
In rental is where all the "rentings" go when you book a car and all the vehicles is stored in vehicle. This is the query I made that almost works.
SELECT vehicle.id,COUNT(rental.vid) as rented,IFNULL(rental.vid,0) as nothing, vehicle.make as make, vehicle.model as model, vehicle.regnr as regnr, vehicle.color as color, vehicle.state as state, vehicle.imgurl as img, vehicle.description as description, vehicle.id
FROM rental,vehicle
WHERE vid = vehicle.id GROUP BY vid
and will print out this:
The rest which doesn't have a value (never been rented) isn't there, I have tried a lot of different ways with IFNULL but haven't gotten anywhere.
Select from Vehicle table and Left Join to Rental table. This will include Vehicle that have never been Rented and their Count(rental.vid) will be 0:
SELECT vehicle.id
,COUNT(rental.vid) as rented
, vehicle.make as make
, vehicle.model as model
, vehicle.regnr as regnr
, vehicle.color as color
, vehicle.state as state
, vehicle.imgurl as img
, vehicle.description as description
FROM vehicle
left join rental on vid = vehicle.id
GROUP BY vehicle.id
Here is a simplified example
The implicit join you have in your example is equivalent to an inner join. With a left join you select all rows you want from your source table. If there are matches to the table you are left joining to, they will appear as well. It's a good way to append data to your source table.
Suppose I have 3 different tables relationships as following
1st is tbl_users(id,gender,name)
2nd is tbl_feeds(id,user_id,feed_value)
3rd is tbl_favs(id,user_id,feed_id)
where id is primary key for every table.
Now suppose I want to get data where those feeds should come which is uploaded by Gender=Male users with one field in every row that should say either the user who is calling this query marked that particular feed as favourite or not.
So final data of result should be like following :
where lets say the person who is calling this query have user_id=2 then is_favourite column should contain 1 if that user marked favourite that particular feed otherwise is_favourite should contain 0.
user_id feed_id feed_value is_favourite gender
1 2 xyz 1 M
2 3 abc 0 M
3 4 mno 0 M
I hope you getting my question , I m able to get feeds as per gender but problem is I m facing problem to get is_favourite flag as per particular user for every feed entry.
I hope some one have these problem before and I can get help from those for sure.
I would be so thankful if some one can resolve my this issue.
Thanks
Something like this should work:
SELECT
u.id AS user_id.
fe.id AS feed_id,
fe.feed_value,
IFNULL(fa.is_favourite, 0),
u.gender
FROM
tbl_users u
JOIN
tbl_feeds fe ON (fe.user_id = u.id)
LEFT JOIN
tbl_favs fa ON (
fa.user_id = u.id
AND
fa.feed_id = fe.id
)
In order to link your tables, you need to find the most common link between them all. This link is user_id. You'll want to create a relationship between all tables with JOIN in order to make sure each and every user has data.
Now I don't know if you're planning on making sure all tables have data with the user_id. But I would use INNER JOIN as it will ONLY show records of that user_id without nulls. If the other tables could POSSIBLY (Not always guaranteed) you should use a LEFT JOIN based on the tables that is it possible with.
Here is an SQLFiddle as an example. However, I recommend you name your ID fields as appropriate to your table's name so that way, there is no confusion!
To get your isFavorite I would use a subquery in order to validate and verify if the user has it selected as a favorite.
SELECT
u.userid,
u.gender,
f.feedsid,
f.feedvalue,
(
SELECT
COUNT(*)
FROM
tbl_favs a
WHERE
a.userid = u.userid AND
a.feedsid = f.feedsid
) as isFavorite
FROM
tbl_users u
INNER JOIN
tbl_feeds f
ON
u.userid = f.userid
~~~~EDIT 1~~~~
In response to your comment, I have updated the SQLFiddle and the query. I don't believe you really need a join now based on the information given. If you were to do a join you would get unexpected results since you would be trying to make a common link between two tables that you do not want. Instead you'll want to just combine the tables together and do a subquery to determine from the favs if it is a favorite of the user's.
SQLFiddle:
SELECT
u.userid,
f.feedsid,
u.name,
u.gender,
f.feedvalue,
(
SELECT
COUNT(*)
FROM
tbl_favs a
WHERE
a.userid = u.userid AND
a.feedsid = f.feedsid
) as isFavorite
FROM
tbl_users u,
tbl_feeds f
ORDER BY
u.userid,
f.feedsid
I have two tables - band and comments. Comments table holds record if any comment has been made on a specific band in the band table. I need number of comments made on a band with all the details from band table. So here is my query
select band.*, count(comments.band) as count from band left join comments on band.id = comments.band
However this query fetches only records that matches both the table. I need all the band table records to be listed even if there is no matching record for it in the comments table (main reason for using left join) Any help?
I think it will work perfectly-
SELECT
band.*, COUNT(comments.band) AS count_no
FROM
band
LEFT JOIN
comments ON band.id = comments.band
GROUP BY band.id;
SQLfiddle:
http://sqlfiddle.com/#!9/986c8/6
SELECT b.name, count(c.band_id) AS comment_count
FROM band AS b
LEFT JOIN comments AS c
ON b.id = c.band_id
GROUP BY b.name;
EDIT: Looks like some people beat me to it!
That query looks correct to me except you don't have a GROUP BY clause. Without a GROUP BY it will only return 1 row with the count for all rows in it. You can use the band tables primary key. ie GROUP BY band.id
I have two tables, one for downloads and one for uploads. They are almost identical but with some other columns that differs them. I want to generate a list of stats for each date for each item in the table.
I use these two queries but have to merge the data in php after running them. I would like to instead run them in a single query, where it would return the columns from both queries in each row grouped by the date. Sometimes there isn't any download data, only upload data, and in all my previous tries it skipped the row if it couldn't find log data from both rows.
How do I merge these two queries into one, where it would display data even if it's just available in one of the tables?
SELECT DATE(upload_date_added) as upload_date, SUM(upload_size) as upload_traffic, SUM(upload_files) as upload_files
FROM packages_uploads
WHERE upload_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY upload_date
ORDER BY upload_date DESC
SELECT DATE(download_date_added) as download_date, SUM(download_size) as download_traffic, SUM(download_files) as download_files
FROM packages_downloads
WHERE download_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY download_date
ORDER BY download_date DESC
I want to get result rows like this:
date, upload_traffic, upload_files, download_traffic, download_files
All help appreciated!
Your two queries can be executed and then combined with the UNION cluase along with an extra field to identify Uploads and Downloads on separate lines:
SELECT
'Uploads' TransmissionType,
DATE(upload_date_added) as TransmissionDate,
SUM(upload_size) as TransmissionTraffic,
SUM(upload_files) as TransmittedFileCount
FROM
packages_uploads
WHERE upload_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY upload_date
ORDER BY upload_date DESC
UNION
SELECT
'Downloads',
DATE(download_date_added),
SUM(download_size),
SUM(download_files)
FROM packages_downloads
WHERE download_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY download_date
ORDER BY download_date DESC;
Give it a Try !!!
What you're asking can only work for rows that have the same add date for upload and download. In this case I think this SQL should work:
SELECT
DATE(u.upload_date_added) as date,
SUM(u.upload_size) as upload_traffic,
SUM(u.upload_files) as upload_files,
SUM(d.download_size) as download_traffic,
SUM(d.download_files) as download_files
FROM
packages_uploads u, packages_downloads d
WHERE u.upload_date_added = d.download_date_added
AND u.upload_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY date
ORDER BY date DESC
Without knowing the schema is hard to give the exact answer so please see the following as a concept not a direct answer.
You could try left join, im not sure if the table package exists but the following may be food for thought
SELECT
p.id,
up.date as upload_date
dwn.date as download_date
FROM
package p
LEFT JOIN package_uploads up ON
( up.package_id = p.id WHERE up.upload_date = 'etc' )
LEFT JOIN package_downloads dwn ON
( dwn.package_id = p.id WHERE up.upload_date = 'etc' )
The above will select all the packages and attempt to join and where the value does not join it will return null.
There is number of ways that you can do this. You can join using primary key and foreign key. In case if you do not have relationship between tables,
You can use,
LEFT JOIN / LEFT OUTER JOIN
Returns all records from the left table and the matched
records from the right table. The result is NULL from the
right side when there is no match.
RIGHT JOIN / RIGHT OUTER JOIN
Returns all records from the right table and the matched
records from the left table. The result is NULL from the left
side when there is no match.
FULL OUTER JOIN
Return all records when there is a match in either left or right table records.
UNION
Is used to combine the result-set of two or more SELECT statements.
Each SELECT statement within UNION must have the same number of,
columns The columns must also have similar data types The columns in,
each SELECT statement must also be in the same order.
INNER JOIN
Select records that have matching values in both tables. -this is good for your situation.
INTERSECT
Does not support MySQL.
NATURAL JOIN
All the column names should be matched.
Since you dont need to update these you can create a view from joining tables then you can use less query in your PHP. But views cannot update. And you did not mentioned about relationship between tables. Because of that I have to go with the UNION.
Like this,
CREATE VIEW checkStatus
AS
SELECT
DATE(upload_date_added) as upload_date,
SUM(upload_size) as upload_traffic,
SUM(upload_files) as upload_files
FROM packages_uploads
WHERE upload_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY upload_date
ORDER BY upload_date DESC
UNION
SELECT
DATE(download_date_added) as download_date,
SUM(download_size) as download_traffic,
SUM(download_files) as download_files
FROM packages_downloads
WHERE download_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY download_date
ORDER BY download_date DESC
Then anywhere you want to select you just need one line:
SELECT * FROM checkStatus
learn more.
With 1001 possibilities to use MySQL, I've come up with a requirement for myself that I want to figure out, but don't know how. I also ran a Google Search of course and checked Stack Overflow and MySQL Docs, but I didn't get the answer I was looking for.
The situation:
I have 2 tables. One called and containing customers and one containing customer_progress . For your imaging, the customer_progress table can optionally contain data about the progress/status for a customer.
My goal was to join the data from the two tables, and put the customers that do have progress data on top, followed by the customers that do not have progress data; all in 1 query.
So I started writing a query, much like the following:
SELECT
*
FROM
customers AS c
LEFT JOIN
customer_progress AS p
ON
p.customer_id = c.id AND p.year = 2011 // Joining them and selecting the progress for a certain year.
WHERE
c.active = 1;
How can I put the customers that do have a progress record first, and then afterwards all the customers that do not have a progress record?
I don't know if I am going the right way with the query or that I need to approach this from a whole different angle. Using a ORDER BY made no sense.
You need to select a customer progress_field that you can order by so that you add something like
order by custer_progress_field desc;
at the end of your select statement.
For example:
SELECT
c.filed1, p.field1
FROM
customers AS c
LEFT JOIN
customer_progress AS p
ON
p.customer_id = c.id AND p.year = 2011 // Joining them and selecting the progress for a certain year.
WHERE
c.active = 1;
Order by p.field1 desc;
You need to add something like
ORDER BY IF(p.customer_id IS NULL,1,0), [other fields]
// or you can do just if sorting by customer_id is acceptable
ORDER BY p.customer_id DESC
You can check more details about how columns with NULL values are treated by ORDER BY on http://dev.mysql.com/doc/refman/5.0/en/working-with-null.html