Joining & Grouping SQL Results - mysql

I'm building a small cinema booking system PHP web application,
The database has a Film and Showing table. (amongst others but not important)
A Showing has a date and a time, and each Showing consists of one Film
A Film can have many Showings
I'm trying to build a query that will get all the film_name, showing_date and showing_time although I want to group the results so I don't have multiple films in the result, as you can have more than one showing on the same date.
I have this SQL:
SELECT f.film_name, s.showing_date, s.showing_time
FROM film f, showing s
WHERE f.film_id = s.film_id
GROUP BY s.film_id
However it's not showing all the times for each film, just the first one. I guess there is a lot I'm missing out, and maybe I should split the showing times into a separate table, but any help would be greatly appreciated. I will most more information and diagrams if necessary.
Thanks

Assuming you want one row per film, with all showings in the same row, try:
SELECT f.film_name, group_concat(concat(s.showing_date, s.showing_time)) showings
FROM film f, showing s
WHERE f.film_id = s.film_id
GROUP BY s.film_id

You cannot do what you are asking to do.
Each row in your result set can only show one film name and one show time. If film A is showing 5 times, then you can either get a result set of five lines, all listing film A and the different show times, or if you group by film A, you will only get one result, and it will list the first show time.

Based upon what you have told us, I believe what you are looking for is some way to condense each film into one row that still lists the showing dates and times properly. In order to do this, you will need to somehow collapse these rows into one row in a way that is not often used. Normall you would use some sort of function on these rows (SUM, COUNT, etc.) to give aggregate data. However, it sounds like you want to see the actual data.
To do this, there is a really helpful SO question here:
Concatenate many rows into a single text string?
The second-highest rated response talks about using XML PATH, which would probably be the cleanest way of doing it if your database supports that feature. If not, look at the accepted answer (COALESCE). I would suggest putting this type of code into a scalar function that returned one field with comma-separated showtimes for you. Then you could list a film and have a list of showtimes next to the film.

Sorry for the confusing and maybe wasting of time, I think I have found the solution by splitting the showing times into a separate table.
I find all of the films being shown on a certain date, then loop through and select all the showing times for those films based on the showing id returned from the first query, as there will only be on showing of a film per day. I add this information to the first result per loop cycle and pass the whole data back.
There's probably better way's of doing it, but this will do for now.
Thanks

Related

Pager for query with many relations and fields

I have a quite complex view with two queries (a view in a view), one select users with related data and another one select orders with related data. Both of them have some filters, but now I have an issue and I am looking for proper and just decent solution, with good performance because I have a lot of data and relationships in the queries.
Assume I have:
Query 1 - Select user data, some left joins to other tables, conditions depends on provided parameters.
Query 2 - Select orders depends on users from Query 1, many joins, conditions depends on parameters.
I display data from two queries in one view, users, their data, orders, and some orders data and now I want to implement pager, but it has to work and display proper number of users depends on filters form Query 1 and Query 2. So there is an issue that I can't really limit from any query cuz another one has filters as well so maybe those users maybe aren't really selected to display depends on other query filters.
So I guess there are two ways, one is to put those queries in loop and collect data until I get proper number of results depends on query.
Another way is to merge those two queries into one, but there an issue that I get many rows per user, so I can't set any page limit and get results only for specific number of users, like for example 30. Because results will be like user 1 => order 1, user 1 => order 2, so is there any way to get specific number of unique results depends on user id or something.
Let me know if you have any questions.
Sample data will make more sense. I am unable to understand the whole requirement here in your question. will you be able to create some sample data and share with us ? if you are dealing with a lot of data, avoid loops as that will just make performance worse.

Repeatable Multi-Colum Data Rows in Wordpress Custom Post Type

I'm moving a sports website from .asp to wordpress.
I have two custom post types:
Players
Tournaments
I need to be able to enter scores into the tournaments for players from the player post type.
The scoring tablulation is as follows:
Player ID First Name Last Name City State Points Place Scores
And I need to be able to add more rows, selecting the players to add the above info for.
The current ASP tables look like this, for each tournament:
And I need to be able to add unlimited rows (repeater).
It would be easy if it was just one column, I could use something like Advanced Custom Fields repeater field, but I do not know how to add rows of related multi-column data, which I can then query and display on the front-end.
Also, I would make each scoring row it's own post, but it would be waaay too many posts.
What I want, is for each tournament (stored in the tournaments CPT), to be able to add the scoring rows there, selecting the player from the player post type, and filling out the columns, as seen, with the ability to add as many rows as there are players for each tournament.
Thank you for your help follow programmers! I've been doing this a fairly long time, but this is a new use-case for me.
You can use Meta Box Group plugin. It allows you to create repeatable group of fields.
So, in your situation, you need to create a group of player (post field), first name, last name, city, state, points, place, score. Then make the whole group repeatable. (In Meta Box, it uses another term clone).

Microsoft Access sql, counting how many times a user chosen value appears, displaying related values

I am creating a query in microsoft access that should count the number of times the instructor ID value, which the user will choose, appears in the Instructor column in the class table, and should display this in the query output.
It should also display the instructorID, InsFirstName and InsSurname values from the Instructor table which correspond to the value entered by the user, as the value appears in both tables.
The code i have so far is:
SELECT COUNT (Instructor)
FROM Instructor, class
WHERE Instructor = [Enter Instructors ID]
GROUP BY Instructor.InstructorID, Instructor.InsFirstName, Instructor.InsSurname;
This however will just display how many times each value in the column appears, rather than just how many times the value the user entered appears. It will also not display the instructorID, InsFirstName and InsSurname values.
Ive included an image of the output here.
The 2 tables i am using are:
Class table
And the instructor table
If any more information or clarification is requested to help with this i will provide it as soon as possible. Thank you in advance to anyone who provides any help.
There are a couple problems here:
1) If you want a field to appear in the output, you need to include it in the SELECT portion of the SQL statement. Anything that is not listed there will not appear in your results. You can also use Count(*) if you want to count the records that match within a grouping.
2) You are querying two tables, Instructor and class, but you haven't specified how the two are joined. Either add a condition to the WHERE clause to specify how they are related (ie. "and Instructor.InstructorID = class.Instructor.ID"), or use a JOIN statement (ie. FROM Instructor INNER JOIN class ON Instructor.InstructorID = class.InstructorID)
Try fixing both of those, hope that helps!

SQL query and for loops

I need a bit of help with a MySQL query. Right now I have a table that has 3 columns: location, street, and number. I want to write a query whose pseudocode would be...
for each location:
for each of the streets of a location
find the next biggest number
I feel like I am still thinking in "for-loop" logic, but that doesn't really seem to be the way MySQL operates, and it is tripping me up. Any help is greatly appreciated!
Also the primary key is the location-street combo
If I understand you right, you want the highest number of each street in each location?
SELECT
location,
street,
MAX(number)
FROM table
GROUP BY
location,
street
First of all, GROUP BY aggregates ("collapses") rows, so that only one row per location and street will be returned. In the list of rows to return, we then explicitly specify we want the highest number (MAX()) instead of the first one that would show up.
http://dev.mysql.com/doc/refman/5.6/en/group-by-handling.html
http://dev.mysql.com/doc/refman/5.6/en/example-maximum-column.html
http://dev.mysql.com/doc/refman/5.6/en/select.html
If it helps, you can think of a SELECT query (albeit very crudely) as filter rules for a loop that goes through every row of the entire table. In these "filter rules" you specify precisely what you want and how you want it, MySQL will then iterate over the entire table and handpick exactly the data you asked for.

Filter a MySQL Result in Delphi

I'm having an issue with a certain requirement to one of my Homework Assignments. I am required to take a list of students and print out all of the students with credit hours of 12 or more. The Credit hours are stored in a separate table, and referenced through a third table
basically, a students table, a classes table with hours, and an enrolled table matching student id to Course id
I used a SUM aggregate grouped by First name from the tables and that all works great, but I don't quite understand how to filter out the people with less than 12 hours, since the SQL doesn't know how many hours each person is taking until it's done with the query.
my string looks like this
'SELECT Students.Fname, SUM(Classes.Crhrs) AS Credits
FROM Students, Classes, Enrolled
WHERE Students.ID = Enrolled.StudentID AND Classes.ID = Enrolled.CourseID
GROUP BY Students.Fname;'
It works fine and shows the grid in the Delphi Project, but I don't know where to go from here to filter the results, since each query run deletes the previous.
Since it's a homework exercise, I'm going to give a very short answer: look up the documentation for HAVING.
Beside getting the desired result directly from SQL as Martijn suggested, Delphi datasets have ways to filter data on the "client side" also. Check the Filter property and the OnFilter record.
Anyway, remember it is usually better to apply the best "filter" on the database side using the proper SQL, and then use client side "filters" only to allow for different views on an already obtained data set, without re-querying the same data, thus saving some database resources and bandwidth (as long as the data on the server didn't change meanwhile...)