Complicated SQL query - how do i do it? - php

I'm currently working on a small feature for a project and wondered how best to achieve the result, i have a table full of reviews with the score being out of 5 and being stored as score in the database, on one page i want to show how many of each score reviews there are, ie number of 5 star reviews, 4 star etc
But i don't know how best to achieve surely i don't need 5 different queries, that would be awful design would it not ?
Thanks and hope you can help !

Since I do not have your table structure, I would do something similar to this (with appropriate names replaced)
edited SQL based on comments
Select Score, COUNT (*) as NumScores
From MyTableOfScores
Group By Score
Order by Score Desc

You need something like this:
select score, count(*) from reviews group by score

Related

What is the best approach to getting the last x records? Using MySQL Limit and ORDER DESC?

I was wondering if there are any other best/better practices then this as far as performance or optimizations.
EDIT: I'm using PHP7. Should have made that clear, I apologize. I'm doing a volunteer project for a local non-profit and it's setup like this:
Table: Volunteer
pk: v_id
So what I'm doing is:
SELECT * from Volunteer ORDER BY v_id DESC LIMIT 25;
(They want the last 25 to display currently for the "last logs" report.)
EDIT2: The only reason I'm asking this now, we've hit 10k volunteer logs in the system and I'm starting to realize MON-FRI they can add anywhere from 50-100 (or more) logs per day so it quickly adds up.
Try Like this.It is the simplest one so far
Select * from tablename order by column desc limit 5
If you can do it programatically
ORDER it ASC with LIMIT X and then loop through the records backwards.
If you give us your language (PHP, node(javascript), java, etc) we can help you with the backwards loop, but it goes something like this :
for(i=rows.length-1;i>=0;i--){
//do your stuff here
}
If you MUST do it in MySQL
SELECT your results ASC with LIMIT X as a subquery and then wrap in a query ORDER DESC
SELECT
*
FROM
(
SELECT
somecol
FROM
sometable
ORDER BY
the_date ASC
LIMIT 100
) as a
ORDER BY
the_date DESC
UPDATE: The way the question was asked at first it sounded like you wanted the last X results, ordered DESC. I will leave my answer in place in case anyone else comes here looking for that.
What you are doing now with the ORDER BY and LIMIT is the optimal way to do it. To optimize, you may want to SELECT only the columns you need, and make sure you have a unique index on v_id. If you need more optimization than that, you may want to consider archiving old data and vacuuming frequently.

Merging multiple rows with same field in column

I am making a leaderboard for a game server and would like a hand with something.
I have a table in MySQL that looks like this (There are other columns that exist but I want to ignore)
Is there a way to combine each row with the same value in steam_id_64, but with player_name show the last used steam name (Or current from steam) and is it possible to hide the row where steam_id_64 is BOT?
I have php5 if that is helpful. Thank you for the help.
You have to sum up the different columns using sum() function. To avoid those bot entries you can use a condition to test for player_name is not BOT
select
player_name,
sum(kills) as kills,
sum(deaths) as deaths,
sum(assists) as assists,
sum(head_shots) as headshots,
sum(team_kills) as team_kills,
sum(assists_team_attack) as assist_team_attack,
sum(damage) as damage,
sum(hits) as hits,
sum(shots) as shots,
sum(last_alive) as last_alive
group by steam_id_64
where steam_id_64 != "BOT"
To make later handling convenient I have added "... as field_name" to each sum().
Please try this and refine your question if something is missing.
use != for hide the row where steam_id_64 is BOT
Select * from table where steam_id_64 !='BOT'

Count rows by foreign key

I need a little help some a sql queries. To summarise, I have 2 tables. Player (which represents a sports player) and a Goal (which represents a goal a player scores). A Player can have many Goals and linked using a foreign key on the goal table (player_id).
What I want to do is get a list of "top scoring players" (top 5), but I have no idea where to start to do this using MySQL. In PHP I'm getting all the goals, then with each goal counting how many player_id's appear and group them like that (then with the array of players and their goal count, trimming the array down to 5). It works, but I'm almost positive I can do the counting in MySQL.
How should I approach this?
EDIT
Tables look like
Player
ID
Name
Goal
player_id
scored_against
time
SELECT COUNT(PLAYER.PLAYER_ID) as Goals,PLAYER_NAME
FROM PLAYER, GOAL
WHERE GOAL.PLAYER_ID = PLAYER.PLAYER_ID
GROUP BY GOAL.PLAYER_ID
ORDER BY Goals DESC
LIMIT 5

PHP MySQL calculate how many rows have the same data

Ok, well I know I can just say WHERE example='vrvrv' but that's not the case. Ok I have a rating system and whenever a page is rated the page id and the date it was rated is sent to a table in my database. Now on the homepage I want to determine top rated that day, I can easily compare dates but I'm not quite sure how to count how many rows have the same value in the project_id column. It would be amazing if someone could help me out, thanks!
You can use GROUP and COUNT to get duplicates:
SELECT count(`project_id`) AS `duplicates` FROM `table` GROUP BY `project_id` HAVING `duplicates` > 1

Mysql Unique Query

I have a programme listing database with all the information needed for one programme packed into one table (I should have split programmes and episodes into their own) Now since there are multiple episodes for any given show I wish to display the main page with just the title names in ascending and chosen letter. Now I know how to do the basic query but this is all i know
SELECT DISTINCT title FROM programme_table WHERE title LIKE '$letter%'
I know that works i use it. But I am using a dynamic image loading that requires a series number to return that image full so how do I get the title to be distinct but also load the series number from that title?
I hope I have been clear.
Thanks for any help
Paul
You can substitute the DISTINCT keyword for a GROUP BY clause.
SELECT
title
, series_number
FROM
programme_table
WHERE title LIKE '$letter%'
GROUP BY
title
, series_number
There are currently two other valid options:
The option suggested by Mohammad is to use a HAVING clause in stead of the WHERE clause this is actually less optimal:
The WHERE clause is used to restrict records, and is also used by the query optimizer to determine which indexes and tables to use. HAVING is a "filter" on the final result set, and is applied after ORDER BY and GROUP BY, so MySQL cannot use it to optimize the query.
So HAVING is a lot less optimal and you should only use it when you cannot use 'WHERE' to get your results.
quosoo points out that the DISTINCT keyword is valid for all listed columns in the query. This is true, but generally people do not recommend it (there is no performance difference *In some specific cases there is a performance difference***)**. The MySQL optimizer however spits out the same query for both so there is no actual performance difference.
Update
Although MySQL does apply the same optimization to both queries, there is actually a difference: when DISTINCT is used in combination with a LIMIT clause, MySQL stops as soon as it finds enough unique rows. so
SELECT DISTINCT
title
, series_number
FROM
programme_table
WHERE
title LIKE '$letter%'
is actually the best option.
select title,series_number from programme_table group by title,series_number having title like '$letter%';
DISTINCT keyword works actually for a list of colums so if you just add the series to your query it should return a set of unique title, series combinations:
SELECT DISTINCT title, series FROM programme_table WHERE title LIKE '$letter%'
Hey thanks for that but i have about 1000 entries with the same series so it would single out the series as well rendering about 999 programmes useless and donot show.
I however found out away to make it unique and show the series number
SELECT * FROM four a INNER JOIN (SELECT title, MIN(series) AS MinPid FROM four WHERE title LIKE '$letter%' GROUP BY title) b ON a.title = b.title AND a.series = b.MinPid
Hopefully it helps anyone in the future and thank you for the replies :)

Categories