SQL Count and Group By issue - mysql

I have a table Mbr that contains 3 fields, GroupType, LeaderID, and MemberID. Basically, all the members in an organization are divided up into these groups, identified by their leader's unique ID (LeaderID). Each member record also has their own MemberID, and the leaders themselves have a unique MemberID as well. The GroupType just designates whether the group a member is in which is considered a Large, Small, or Individual group.
I need to find out how many groups of each GroupType contain a certain number of members.
For example:
How many Large groups contain 6 members, 7 members, 8 members, 9 and so on.
How many Small Groups contain 2 members, 3 members, 4 members and 5 members
How many Individual groups there are.
Is it possible make a query to get a Count of the unique MemberID's for each group, and then get a COUNT of how many LeaderID's have a certain number of members associated to them?

Note: Since you are not specifying which DBMS you are using, I tried to do a basic query. In SQLServer or Oracle this can be much more elegant.
I'm assuming that a given Member can be Leader leader of only one Group if that is correct,
Question #1:
SELECT GroupType, NumberOfMembers, COUNT(LeaderID) AS NumberOfGroups
FROM (
SELECT GroupType, LeaderID, COUNT(*) AS NumberOfMembers
FROM MyTable
GROUP BY GroupType, LeaderID
) AS InnerGrouping
GROUP BY GroupType, NumberOfMembers
ORDER BY GroupType, NumberOfMembers
Question #2:
SELECT UniqueMemberIDPerGroup, COUNT(LeaderID) AS NumberOfLeaderID
FROM (
SELECT LeaderID, COUNT(DISTINCT MemberID) AS UniqueMemberIDPerGroup
FROM MyTable
GROUP BY LeaderID
) AS InnerGrouping
GROUP BY UniqueMemberIDPerGroup

I'm sure you can write some complex query with several subqueries to create a query to give you what you want, but I personally like more straightforward methods. In this case, it would be using some temp tables to store intermediate values. I would first group by several columns (that you are going to use as criterias) with count being the value for the query. I would then store these into a temp table and finally create a query to utilize the temp table to give you the results that you are looking for.

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.

Mysql IN condition for and operations

I have expertise table that have user id and expertise id. Each user might have multiple expertise. Now I want to get all users that must have all expertise in range, like (1,2,3,4,5,......so on).
IN condition is only used for OR operation so how can I get expected result lets say by using IN condition with AND operation. Or is there any other operator or trick that can be used.
EDIT:
Let me add bit more explanation. Customer select expertise like physics, math, chemistry ...... and so on. So I have expertise and I need to get all user ids from expertise table that satisfy all selected expertise. So I need user who is well versed in math, physics, chemistry and so on.
All data is in one expertise table.
Current query is like this
Select user_id from expertise where expertise_id IN (1,2,3,4)
but this is true for all user who have one of these expertise but I need all users who have all these expertise.
If I understand correctly you want all the user_id returning which have all the expertise (and possibly more) that are in the IN clause.
If so select the users_id, GROUP BY the user id and COUNT the DISTINCT expertise id that match. Return the users_id for those where the count is the same as the number of ids you are searching for.
SELECT user_id
FROM expertise
WHERE expertise_id IN (1,2,3,4)
GROUP BY user_id
HAVING COUNT(DISTINCT expertise_id) = 4
You could verify the number of expertises that match your list, and require that this number equals the size of your list. Here is an example, for when your list of required expertises has 5 elements:
SELECT *
FROM users
WHERE 5 = (SELECT COUNT(DISTINCT expertise_id)
FROM user_expertises
WHERE user_id = users.user_id
AND expertise_id IN (1, 2, 3, 13, 18))
The DISTINCT expertise_id can be replaced by a simple * if it is certain that the user_expertise table has no duplicate (user_id, expertise_id) pairs.
Of course, you'll have to use the proper table names and columns names. This is just a template.

MySQL Union (or similar) query

I have some booking data from a pair of views in MySQL. They match columns perfectly, and the main difference is a booking code that is placed in one of these rows.
The context is as follows: this is for calculating numbers for a sports camp. People are booked in, but can do extra activities.
View 1: All specialist bookings (say: a football class).
View 2: A general group.
Due to the old software, the booking process results in many people booking for the general group and then are upgraded to the old class. This is further complicated by some things elsewhere in the business.
To be clear - View 1 actually contains some (but are not exclusively all) people from within View 2. There's an intersection of the two groups. Obviously people can't be in two groups at once (there's only one of them!).
Finding all people who are in View 2 is of course easy... as is View 1. BUT, I need to produce a report which is basically:
"View 1" overwriting "View 2"... or put another way:
"View 1" [sort of] UNION "View 2"
However: I'm not sure the best way of doing this as there are added complications:
Each row is as approximately (with other stuff omitted) as follows:
User ID Timeslot Activity
1 A Football
1 A General
2 A General
3 A Football
As you can see, these rows all concern timeslot A:
- User 2 does general activities.
- User 3 does football.
- User 1 does football AND general.
AS these items are non unique, the above is a UNION (distinct), as there are no truly distinct rows.
The output I need is as follows:
User ID Timeslot Activity
1 A Football
2 A General
3 A Football
Here, Football has taken "precedence" over "general", and thus I get the picture of where people are at any time.
This UNION has a distinct clause on a number of fields, but ignores others.
So: does anyone know how to do what amounts to:
"add two tables together and overwrite one of them if it's the same timeslot"
Or something like a:
"selective distinct on UNION DISTINCT".
Cheers
Rick
Try this:
SELECT *
FROM
(SELECT *,
IF(Activity='General',1,0) AS order_column
FROM `Table1`
ORDER BY order_column) AS tmp
GROUP BY UserId
This will add an order_column to your original table that as value 1 if the Activity value is general; Doing this we can select this temporary table ordering by this column (ascending order) and all record with general activity comes after all others. After that we can simply select the result of this temporary table grouping by user id. The group by clouse without any aggregate function takes the first record that match.
EDIT:
If you don't to use group by without aggregate function this is an 'ugly' alternative:
SELECT UserId,
Timeslot,
SUBSTRING(MAX(CASE Activity WHEN "General" THEN "00General" WHEN "Football" THEN "01Football" ELSE Activity END) , 3)
FROM `Table1`
GROUP BY UserId,
Timeslot LIMIT 0 ,
30
Here we need to define each possible value for Activity.

Query using two tables with DISTINCT

I have two tables - clients and - group
I need to get county and zip from clients and group-assigned from group
When I search, I cannot get distinct results, that is, instead of the output showing 100 clients with zipcode 12345 in jones county in main st group.
I need to have each zip and county listed once by group. I have googled and attempted many ways but it is just beyond me.
Can anyone assist in steering me to the correct way
Adding GROUP BY group, city, zip to the end of your query should get you what you need. It will only return unique combinations of the three.
Presumably you have something like:
select g.*, c.county, c.zip
from clients c join groups g on <some join condition>
You want one result per group. So, add a group by clause such as:
group by g.id -- assuming id uniquely identifies each group
This will give an arbitrary value for the other fields, which may be sufficient for what you are doing. (This uses a MySQL features called Hidden Columns.)

What's the best way to combine 2 tables in MYSQL and remove duplicates?

I have 2 tables:
matches TABLE
FIELDS: record, date, competition
outrights TABLE
FIELDS: record, competition
What I would like, is to select rows grouped by the different types of competition. Below are the statements that work fine when I treat each table seperately.
Firstly, from 'matches' and only if the date hasn't already past:
SELECT competition, date FROM matches WHERE date >= '$currentTime' GROUP BY competition
Followed by rows from 'outrights':
SELECT competition FROM outrights GROUP BY competition
This is all pretty straight forward, except the same competition values will often (but not always) appear in both tables. I have looked at many different methods (including LEFT and RIGHT JOINS), but haven't found a simple solution. Basically I want the different competition types that appear in both tables, without duplication. Is this possible?
Is this what you are looking for. A little confused by the question but it appears that you want a DISTINCT listing of the competition column from both tables
SELECT DISTINCT competition
FROM
(
SELECT competition FROM matches
UNION
SELECT competition from outrights
) AS t
If you need the distinct competitions that appear only in both tables and not just one or both you could use
SELECT DISTINCT competition
FROM
(
SELECT competition FROM matches INNER JOIN
outrights ON matches.competition = outrights.competition
) AS t