I have a table which holds a customer and another table which holds results from that customer.
One customer can have many results.
I want to be able to firsly select only the customers which have more than one entry in CustResults, and then from those, I want all the records except the first one...
I have this so far, which retrieves the customers with more than one result, but I don't know how to then ingore then first result.
SELECT * FROM CustResults cp
JOIN Customer c ON c.CustomerID = cp.CustomerID
WHERE
(SELECT count(CustomerID) as cpid
FROM CustResults WHERE CustomerID = cp.CustomerID GROUP BY CxID) > 1
i.e.
Rita: RESULT 1
Sue: RESULT 1, Result 2, Result 3, Result 4
Bob: RESULT 1, Result 2, Result 3
I only want Sue and Bob, as Rita only has one result, and from Sue and Bob, I only want to look at results 2,3,4
Any ideas?
Thanks
ADDED MORE INFO:
Here is my exact query:
SELECT count(cp.CxID) as intSmokers
FROM CustPrimarySmoking cp
JOIN Customer c ON cp.CxID = c.CustomerID
WHERE (SELECT count(CustPrimarySmokingID) as cqpid FROM CustPrimarySmoking WHERE CxID = cp.CxID GROUP BY CxID) > 1
Obviously, I can just use LIMIT 1, 99999, because the query is only returning one value (the count).
I want the count to be using the customers with more than one record in CustPrimarySmoking, but ignoring the first entry.
Any futher ideas?
Stupid and not-so flexible (however, it should works all most of the time) ...
LIMIT 1, 999999999;
^ to ensure all rows are returned
Have you tried to add "OFFSET 1" at the end of the query?
If all you are after is the count and not the actual records then you just need to subtract the number of customers from the count you already have (as you have already ascertained that each as at least one record) i.e.
SELECT count(cp.CxID)-count(DISTINCT cp.CxID) as intSmokers
FROM CustPrimarySmoking cp
JOIN Customer c ON cp.CxID = c.CustomerID
WHERE (
SELECT count(CustPrimarySmokingID) as cqpid
FROM CustPrimarySmoking WHERE CxID = cp.CxID
GROUP BY CxID
) > 1
If however you are after the actual rows, how about this:
SELECT * FROM Customer;
+------------+------+
| CustomerID | name |
+------------+------+
| 1 | Rita |
| 2 | Sue |
| 3 | Bob |
| 4 | Jack |
+------------+------+
SELECT * FROM CustPrimarySmoking;
+----------------------+------+-------------------+
| CustPrimarySmokingID | CxID | result |
+----------------------+------+-------------------+
| 1 | 1 | Result 1 for Rita |
| 2 | 2 | Result 1 for Sue |
| 3 | 2 | Result 2 for Sue |
| 4 | 2 | Result 3 for Sue |
| 5 | 2 | Result 4 for Sue |
| 6 | 3 | Result 1 for Bob |
| 7 | 3 | Result 2 for Bob |
| 8 | 3 | Result 3 for Bob |
+----------------------+------+-------------------+
SELECT * FROM CustPrimarySmoking cp
JOIN Customer c ON cp.CxID = c.CustomerID
WHERE CustPrimarySmokingID <> (
SELECT CustPrimarySmokingID
FROM CustPrimarySmoking
WHERE CxID = cp.CxID ORDER BY CustPrimarySmokingID LIMIT 1
);
+----------------------+------+------------------+------------+------+
| CustPrimarySmokingID | CxID | result | CustomerID | name |
+----------------------+------+------------------+------------+------+
| 3 | 2 | Result 2 for Sue | 2 | Sue |
| 4 | 2 | Result 3 for Sue | 2 | Sue |
| 5 | 2 | Result 4 for Sue | 2 | Sue |
| 7 | 3 | Result 2 for Bob | 3 | Bob |
| 8 | 3 | Result 3 for Bob | 3 | Bob |
+----------------------+------+------------------+------------+------+
Related
NOTE: This is not the same as this question, as I need to get data from two other records, not two fields from one one other record!
MySQL newb. I have two tables, and I want to get data from both of them so I have the following:
wp_bowling_fixtures
fixture_id | fixture_date | home_team_id | away_team_id
-----------+--------------+--------------+-------------
1 | 2017-12-12 | 1 | 2
2 | 2017-12-12 | 3 | 4
3 | 2017-12-12 | 5 | 6
4 | 2017-12-12 | 7 | 8
5 | 2017-12-12 | 9 | 10
wp_bowling_teams
team_id | name | division | archived
--------+--------+----------+---------
1 | Team A | 1 | 0
2 | Team B | 1 | 0
3 | Team C | 2 | 1
4 | Team D | 2 | 0
5 | Team E | 3 | 0
6 | Team F | 3 | 0
7 | Team G | 4 | 0
8 | Team H | 4 | 1
9 | Team I | 4 | 0
10 | Team J | 4 | 0
The result I want a SELECT query to produce:
fixture_id | fixture_date | home_team_id | home_team_name | home_team_archived | home_team_division | away_team_id | away_team_name | away_team_archived | away_team_division
-----------+--------------+--------------+----------------+--------------------+--------------------+--------------+----------------+--------------------+-------------------
1 | 2017-12-12 | 1 | Team A | 0 | 1 | 2 | Team B | 0 | 1
I also want it ordered by fixture_date DESC, home_team_division ASC, home_team_name ASC.
Hope that makes sense.
TIA,
Nick.
SELECT f.fixture_id, f.fixture_date, h.team_id as home_team_id, h.name as home_team_name, h.archived as home_team_archived, h.division as home_team_division, a.team_id as away_team_id, a.name as away_team_name, a.archived as away_team_archived, a.division as away_team_division FROM wp_bowling_fixtures f, wp_bowling_teams h, wp_bowling_teams a where f.home_team_id = h.team_id and f.away_team_id = a.team_id order by f.fixture_date desc, h.division asc, h.name asc;
Works.
Nothing in sql stops you joining a table twice but if you do so you must alias them .
You're looking for a query that uses
fixtures f
JOIN teams h ON f.home_team_id = h.team_id
JOIN teams a ON f.away_team_id = a.team_id
I gave the teams h (for home) and a (for away) aliases so I could tell them apart. Give it a go at filling it out
select x.fixture_id, x.fixture_date, x.home_team_id, x.home_team_name, x.home_team_archived, x.home_team_division,
y.away_team_id, y.away_team_name, y.away_team_archived, y.away_team_division from
(select a.fixture_id, a.fixture_date, a.home_team_id, b.name home_team_name, b.archived home_team_archived, b.division home_team_division
from wp_bowling_fixtures a inner join wp_bowling_teams b on A.home_team_id = B.team_id) x
inner join
(select a.fixture_id, a.fixture_date, a.away_team_id, b.name away_team_name, b.archived away_team_archived, b.division away_team_division
from wp_bowling_fixtures a inner join wp_bowling_teams b on A.away_team_id = B.team_id) y on x.fixture_id = y.fixture_id
order by x.fixture_date desc, home_team_division asc, home_team_name asc;`enter code here`
I'm trying to return a list of users, ordered by a field (pt_seen) on the users most recent row.
Does that make sense?
So far I have:
SELECT u.users_id,
u.username,
ed.date
FROM users u
LEFT JOIN exercises_done ed
ON ed.user_id = u.users_id
WHERE u.pt_id = 1
GROUP BY u.users_id
Which obviously just returns the users grouped.
The tables look like this:
users:
users_id | pt_id | username
1 | 1 | billy
2 | 1 | bob
3 | 1 | sue
exercises_done:
exercises_done_id | user_id | pt_id | exercises_done_date | pt_seen
1 | 1 | 1 | 2018-01-01 | 0
2 | 1 | 1 | 2018-01-02 | 0
3 | 1 | 1 | 2018-01-03 | 1
4 | 2 | 1 | 2018-01-05 | 1
5 | 3 | 1 | 2018-01-04 | 0
and I'm trying to get results like this:
users_id | username | exercises_done_date | pt_seen
1 | billy | 2018-01-02 | 0
3 | sue | 2018-01-04 | 0
2 | bob | 2018-01-05 | 1
The aim is that I show users at the top of the list who have a pt_seen value of 0, then ordered by exercises_done_date.
Any help would be great,
You can select the most recent exercise in the where clause rather than using aggregation:
SELECT u.users_id, u.username, ed.*
FROM users u LEFT JOIN
exercises_done ed
ON ed.user_id = u.users_id
WHERE ed.exercises_done_date = (SELECT MAX(ed2.exercises_done_date)
FROM exercises_done ed2
WHERE ed2.user_id = ed.user_id
) AND
u.pt_id = 1
ORDER BY u.pt_seen, exercises_done_date DESC;
You can add an ORDER BY clause after your GROUP BY.
SELECT u.users_id, u.username, ed.date FROM
users u
LEFT JOIN exercises_done ed ON ed.user_id = u.users_id
WHERE
u.pt_id = 1
GROUP BY
u.users_id
ORDER BY
pt_seen, exercises_done_date
It's the 3rd day I'm trying to write a MySQL query. Did lots of search, but it still doesn't work as expected. I'll try to simplify tables as much as possible
System has tkr_restaurants table:
restaurant_id | restaurant_name
1 | AA
2 | BB
3 | CC
Each restaurant has a division assigned (tkr_divisions table):
division_id | restaurant_id | division_name
1 | 1 | AA-1
2 | 1 | AA-2
3 | 2 | BB-1
Then there are meals in tkr_meals_to_restaurants_divisions table, where each meal can be assigned (mapped) to whole restaurant(s) and/or specific division(s). If meal is mapped to restaurant, all restaurant's divisions should see it. If meal is mapped to division(s), only specific division(s) should see it.
meal_id | mapped_restaurant_id | mapped_division_id
1 | 1 | NULL
2 | NULL | 1
3 | NULL | 2
I need to display a list of restaurants and number of meals mapped to it depending on user permissions.
Example 1: if user has permissions to access whole restaurant_id 1 and restaurant_3 (and no specific divisions), then list should be:
AA | 3
CC | 0
(because user can access meals mapped to restaurant 1 + all its division, and restaurant 3 + all its divisions (even if restaurant 3 has no divisions/meals mapped))
Example 2: if user has permissions to access only division_id 1, then list should be:
AA | 1
(because user can only access meals mapped to division 1).
The closest query I could get is:
Example 1:
SELECT *,
(SELECT COUNT(DISTINCT meal_id)
FROM
tkr_meals_to_restaurants_divisions
WHERE
tkr_meals_to_restaurants_divisions.mapped_restaurant_id=tkr_restaurants.restaurant_id
OR tkr_meals_to_restaurants_divisions.mapped_division_id=tkr_divisions.division_id)AS total_meals
FROM
tkr_restaurants
LEFT JOIN
tkr_divisions
ON tkr_restaurants.restaurant_id=tkr_divisions.restaurant_id
WHERE
tkr_restaurants.restaurant_id IN (1, 3)
OR tkr_restaurants.restaurant_id IN (
SELECT restaurant_id
FROM tkr_divisions
WHERE division_id IN (NULL)
)
GROUP BY
tkr_restaurants.restaurant_id
ORDER BY
tkr_restaurants.restaurant_name
However, result was:
AA | 2
CC | 0
I believe I'm greatly over-complicating this query, but all the simpler queries I wrote produced even more inaccurate results.
What about this query:
SELECT
FROM tkr_restaurants AS a
JOIN tkr_divisions AS b
ON a.restaurant_id = b.restaurant_id
LEFT OUTER JOIN tkr_meals_to_restaurants_divisions AS c
ON (c.mapped_restaurant_id = a.restaurant_id OR c.mapped_division_id = b.division_id)
As a Base four your further work. It combine all information into one table. If you add e.g. this:
WHERE a.restaurant_id IN (1, 3)
the result will be
| restaurant_id | restaurant_name | division_id | restaurant_id | division_name | meal_id | mapped_restaurant_id | mapped_division_id |
|---------------|-----------------|-------------|---------------|---------------|---------|----------------------|--------------------|
| 1 | AA | 1 | 1 | AA-1 | 1 | 1 | (null) |
| 1 | AA | 2 | 1 | AA-2 | 1 | 1 | (null) |
| 1 | AA | 1 | 1 | AA-1 | 2 | (null) | 1 |
| 1 | AA | 2 | 1 | AA-2 | 3 | (null) | 2 |
just count the distinct meal ids with COUNT(DISTINCT c.meal_id) and take the restaurant name to get AA: 3 for your example 2
I used a sqlfiddle: http://sqlfiddle.com/#!9/fa2b78/18/0
[EDIT]
Change JOIN tkr_divisions AS b to LEFT OUTER JOIN tkr_divisions AS b
Change SELECT * to SELECT a.restaurant_name, COUNT(DISTINCT c.meal_id)
Add a GROUP BY a.restaurant_name at the end.
Update the SQL Fiddle (new link)
I have 2 tables, the first table or_f_table data. The second table or_table
or_f_table
f_id | f_o_id | f_u_id
1 | 19 | 1
2 | 5 | 2
3 | 19 | 2
or_table
o_id | o_name
4 | test1
5 | test2
19 | oops2
20 | oops3
SELECT o.o_name,
IF ((SELECT count(*) FROM or_f_table as f
WHERE f.f_u_id = 1 ),'Yes','No') as follow_status
FROM or_table as o
WHERE o.o_name LIKE '%oop%'
I want to do something like this result :-
o_name | follow_status
oops2 | Yes
oops3 | No
I am getting result
o_name | follow_status
oops2 | Yes
oops3 | Yes
Why doesn't it work? And how should I correct it
There will always be a value greater than 0 for your where condition. That is why it is not working.
Try this to get the specified results
SELECT o.o_name,
IF ((SELECT count(*) FROM or_f_table as f
WHERE f.f_o_id = o.o_id ),'Yes','No') as follow_status
FROM or_table as o
WHERE o.o_name LIKE '%oop%'
I'm having trouble coming up with a query that returns the player's id, name along with the player's first match date, matchid and opponent.
I want the same information for player's last match as well.
`players`
id | name
1 | playername10
2 | playername22
3 | playername33
4 | playername45
5 | playername55
`matches`
id | gamedate | opponent
1 | 2011-01-01 | opponent1
2 | 2011-01-02 | opponent2
3 | 2011-01-03 | opponent3
4 | 2011-01-04 | opponent4
5 | 2011-01-05 | opponent5
`playermatchscores`
id | matchid | player | goals
1 | 1 | playername10 | 1
2 | 1 | playername22 | 2
3 | 2 | playername10 | 1
4 | 1 | playername33 | 1
5 | 3 | playername45 | 2
6 | 4 | playername55 | 1
7 | 2 | playername55 | 1
8 | 3 | playername22 | 2
9 | 5 | playername55 | 1
Where matchid is a foreign key to the id in table matches.
I tried several queries but I may be approaching it the the wrong way. How can I write a way to get the information I want?
Information about LEFT JOIN: http://www.w3schools.com/sql/sql_join_left.asp
SELECT players.id, MAX(matches.gamedate) AS first_match, MIN(matches.gamedate) AS last_match
FROM playermatchscores
LEFT JOIN players ON players.player = playermatchscores.player
LEFT JOIN matches ON matches.id = playermatchscores.matchid
GROUP BY players.player
I haven't tested this select.
P.S. You should use foreign key for players table too with player_id in playermatchscores.
After the changes in question:
SELECT players.*, matches.*,
FROM playermatchscores
LEFT JOIN players ON players.name = playermatchscores.player
LEFT JOIN matches ON matches.id = playermatchscores.matchid
ORDER BY matches.gamedate ASC
WHERE players.id = 3
LIMIT 1
For the last match replace ASC with DESC.
P.S. This is not the best way to do it but it should work.