How to Calculate percent in single query sakila format - mysql

i am working with table film in mysql
The columns is film_id (primary key), category ( kind of movie), Length (in min)
I have to use single query, without sub-query and find:
for each category of films-percentage of films that are longer than two hours.
romantic-63%
horror-70%
I try maybe to replicate the column of id but it doesn't work

I'm not able to do a test run of this at the moment, but perhaps you can? Off the top of my head I'd try something like this:
SELECT f1.category, (count(f2.*)*100/count(f1.*)) AS percent
FROM film f
LEFT JOIN film f2 ON f1.film_id = f2.film_id
WHERE f2.length > 120
GROUP BY f1.category
ORDER BY f1.category;

Related

Accessing multiple tables at the same time and multiplying values in SQL

My problem is very specific and I couldn't figure out a better name for the title.
I have 3 tables, which are Pessoa (Person), Bicicleta (Bicicle) and Viagem (Trip):
What I want to do is select the names of the individuals by alphabetic order who had a trip, together with the Avaliacao (Evaluation) multiplied by Valor_Viagem (Trip cost).
What I tried to do (not working properly nor finished):
select distinct PESSOA.Nome, VIAGEM.Avaliacao, VIAGEM.Id_Bicicleta, BICICLETA.Valor_Viagem from PESSOA, VIAGEM
join BICICLETA ON VIAGEM.Id_Bicicleta = BICICLETA.Id where PESSOA.Email IN (
SELECT Email_Utilizador FROM VIAGEM
);
Which gives me:
^This is NOT what I want, as stated before.
I am also not 100% sure what you are looking for, but I assume you need a list of distinct names that contains the Avalacao * Valor_Viagem summed for each person (so a person with 5 trips has five times Avalacao * Valor_Viagem + ... + ...).
That is very easy to achieve:
select PESSOA.Nome, VIAGEM.Avaliacao, VIAGEM.Id_Bicicleta, BICICLETA.Valor_Viagem from PESSOA, VIAGEM, SUM(VIAGEM.Avaliacao * BICICLETA.Valor_viagem) AS trip_cost
join BICICLETA ON VIAGEM.Id_Bicicleta = BICICLETA.Id where PESSOA.Email IN (
SELECT Email_Utilizador FROM VIAGEM
) GROUP BY PESSOA.Nome;
What happens is the following:
first you compute the product for each trip
than you use the GROUP BY clause to group persons with identical names together
using SUM in combination with GROUP BY causes to sum all values of persons within this group, in that case all records with the same PESSOA.Nome
A word of warning
This assumes you will have distinct names. This appears risky. Better assign each person a unique Id and use this Id as foreign key instead of the name.

How to show a data using JOIN in SQL (PHP)

Select maintable.name FROM maintable
JOIN genres genre1 USING (tmdb_id)
JOIN genres genre2 USING (tmdb_id)
WHERE genre1.genres_name = 'Action'
AND genre2.genres_name = 'Drama'
group by maintable.name
Here genres is table name. genres_name is column name. genres1 and genres2 are just nor a table name, nor a column name, they are just random name in the code.
This is my code, now How do i display all genres_name?
The genres is like:
tmdb_id genres_name
1 Action
1 Crime
1 Drama
2 Horror
2 Comedy
2 Drama
The main table isl ike
tmdb_id movie_title
1 The Dark Knight
2 Logan
3 Wonder Woman
Let me know, if you need more information. (Please do not ask to show, what i tried. Trust me, it will make the question more confusing)
I want to echo the genres like:
The Dark Knight - Drama, Action, Crime
Of course, you need to use group_concat:
Select maintable.movie_title, group_concat(genres.genres_name) AS genres_name
FROM maintable
JOIN genres USING (tmdb_id)
GROUP BY maintable.tmdb_id
HAVING find_in_set('Action', genres_name) AND find_in_set('Drama', genres_name)
See demo here.
Note: How does find_in_set works, please see official doc.
I would try something like this. But this is the best I can do guessing at it in my head... ( sorry for any mistakes )
$Sql = "SELECT
m.name,
GROUP_CONCAT( g.genres_name ) as genres_list
FROM
maintable AS m
JOIN
genres AS g USING (tmdb_id)
WHERE
g.genres_name IN('Drama', 'Action')
GROUP BY m.tmdb_id";
MySQL GROUP_CONCAT() function returns a string with concatenated non-NULL value from a group.
http://www.w3resource.com/mysql/aggregate-functions-and-grouping/aggregate-functions-and-grouping-group_concat.php
Also note GROUP_CONCAT has a setting for the length, I don't recall what that is or how to change it, but it bit me in the butt one time. Basically it will truncate the list after a certain size, so be cautious of that.
See here: MySQL and GROUP_CONCAT() maximum length
AS I said I haven't tested this, but it seems you have a many to one relationship. Records in the maintable can have many related records in the genres table. Therefor, you should be able to group them on that relationship. Normally this would return 1 record for each pair ( same record in main table different in genre ) Without the group. The Group Concat allows you to compress that into a comma separated list.

Selecting values where the first 6 characters match

I'm trying to pull a list of IDs from a table Company where the first 6 characters of the ID are the same. The way our application creates a company ID is it takes the first 3 characters of the company name and the first 3 characters of the City. Beceause of that, overtime we have company IDs with the same first 6 characters, followed by a sequential number...
I was thinking using something using LIKE
Select companyID, companyName from Company Where
substring(companyID,1,6)+'%' like substring(companyID,1,6)+'%'
Basically i'm trying to get all company IDs where the first 6 characters match; The result set should show the just the top company ID ( The first 1 created) and the company name. I'm not expecting a tone of results, so i can then use the IDs returned to find the IDs below it.
I'm thinking it could maybe also be done using HAVING, where the count of IDs with the same first 6 characters are the same HAVING Count(*)>1??
Not really sure what the syntax would be...
SELECT distinct c1.CompanyID, c1.CompanyName, c2.CompanyID, c2.CompanyName
FROM dbo.Company c1
JOIN dbo.Company c2
ON SUBSTRING(c1.CompanyName,1,6) = SUBSTRING(c2.CompanyName,1,6)
AND c1.CompanyID < c2.CompanyID
order by c1.CompanyName, c2.CompanyName
SELECT c1.CompanyID, c1.CompanyName, c2.CompanyID, c2.CompanyName
FROM dbo.Company c1
INNER JOIN dbo.Company c2
ON SUBSTRING(c1.CompanyName,1,6) + '%' LIKE SUBSTRING(c2.CompanyName,1,6) + '%'
AND c1.CompanyID <> c2.CompanyID
If this is something that you envision doing frequently, I'd add a computed column to the table that has a definition of substring(CompanyName, 1, 6). You can then index it and make this efficient. As it is, it will have to scan all the entries and calculate the substring on the fly. With the computed column, you amortize the substring calculation up front and at least have a chance at an efficient query.
After trying to use Blam's script, i made a few slight changes and got some better results. His script was returning more results than rows in the table and it was pretty slow; think it's because of the company_name column. I got rid of it and wrote it like this:
select distinct c1.cmp_id, count(substring(c2.cmp_id,1,6)) as TotalCount
from company c1
join company c2 on substring(c1.cmp_id,1,6)=substring(c2.cmp_id,1,6)
group by c1.cmp_id
order by c1.cmp_id asc
This still returns all the table records, but atleast i can see the total count when the first 6 characters are listed more than once. Also, it ran in only 1 second so that's also a plus. Thank again for you input guys, always appreciated!

Selecting rows that do not match criteria of inner join

I have two tables, one that holds lot of links (tvlinks), and another that holds list of substrings to be matched against the name of the links (tvshows):
tvlinks:
id (int 11) - primary index key
name (text) - name of the tv show link
link (text) - link to a website with information about the tv show
tvshows:
id (int 11) - primary index key
name (text) - name of the tv show
match (text) - substring to be matched against name in tvlinks table
there can be multiple rows in tvlinks with exactly the same name and different link. There is no duplicate rows.
i use the following query to get all rows from tvlinks where tvshows.match is a substring of tvlinks.name:
SELECT l.id,
l.name,
l.link
FROM tvlinks tvl
INNER JOIN tvshows tvs
ON ( INSTR(tvl.name, tvs.match )
ORDER BY tvl.name
;
and it works fine, my problem is that i'd like to put together another query that would return only the rows that do not get matched by the query above.
i've been bashing my head on the keyboard on and off for a week or two, and i'm sure its something really simple that i'm missing in a big way. :)
Thanks for your help
select id from tvlinks where id not in (select l.id,
FROM tvlinks tvl
INNER JOIN tvshows tvs
ON ( INSTR(tvl.name, tvs.match )
ORDER BY tvl.name
;)
Not efficient per se, all depends on your tables.
INSTR() - Return the index of the first occurrence of substring - not the condition you need

MySQL data fetching

I have trouble to understand how to fetch data from MySQL. Answer might by simple, but i'm stuck, and can't find any help over internet...
I have three tables, let's say first table is named series, second is teams and third id games.
Table structure is something like this:
series:
id
name
teams:
id
name
games:
series_id (relates to series.id)
hometeam_id (relates to teams.id)
visitorteam_id (relates to teams.id)
So my problem is fetching rows from games, where those id's need to be there names, not id's...
Result should be something like this:
"championship
wolverines
marines"
not like
"1
45
142"
Currently i'm fetching those series and teams tables to hashref (in perl) and taking id's from there. But there must be more efficient way to do that in one sql query instead of three.
You need to join the teams table twice (once for home team, second time for visitors)
SELECT g.*,h.name as hometeam_name,v.name as visitorteam_name FROM games g
INNER JOIN series s ON g.series_id=s.id
INNER JOIN teams h ON g.hometeam_id=h.id
INNER JOIN teams v ON g.visitorteam_id=v.id