I have the following query which provides me with accurate results:
SELECT t.id
FROM titles t
ORDER BY t.id
My results are:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
My second query also provides me with accurate results:
SELECT t.id
FROM titles t
JOIN subscriptions s
ON t.id = s.title
WHERE s.user=2
Results:
10
11
14
So what I am trying to do is receive all the results from the first query that don't show up in the second query, so I run this:
SELECT t.id
FROM titles t
ORDER BY t.id NOT IN
(
SELECT t.id
FROM titles t
JOIN subscriptions s
ON t.id = s.title
WHERE s.user=2
);
But my results end up as this:
14
11
10
13
12
9
8
7
6
5
4
3
2
1
What am I doing wrong here? Any why is the order reversed in my second query?
NOT IN should be a part of WHERE condition, not ORDER BY statement:
SELECT
t.id
FROM
titles t
WHERE
t.id NOT IN
(
SELECT t.id
FROM titles t
JOIN subscriptions s
ON t.id = s.title
WHERE s.user=2
)
ORDER BY
t.id
Related
I'm new to programming and MySQL and I think this is simple but not for me. So, I have two tables, Tickets and Ticket_user, and I need to get all the fields from the Table Ticket where user_id =15 and ticket_id >8.
Table 1 : Ticket
id name ...... other fields
7 Tickte1
8 Tickte2
9 ticket3
10 ticket4
11 Tickte5
Table 2 : Ticket_users
id ticket_id User_id
1 7 15
2 8 16
3 9 15
4 10 15
5 11 8
Result:
ticket_id name ...... other fields
9 Tickte3
10 ticket4
How can I achieve this?
Both queries will work.
The second is faster if you have to handle a lot of data
First uses IN clause
SELECT
id, name
FROM
Ticket
WHERE
id IN (SELECT
ticket_id
FROM
Ticket_users
WHERE
User_id = 15 AND ticket_id > 7);
second uses INNER JOIN
SELECT
id, name
FROM
Ticket t
INNER JOIN
(SELECT
ticket_id
FROM
Ticket_users
WHERE
User_id = 15 AND ticket_id > 7) ut ON t.id = ut.ticket_id;
You need to look into JOIN CLAUSE.
What your looking for is something like this
SELECT t.*
FROM Ticket t LEFT JOIN Ticket_users tu ON t.id = tu.ticket_id
WHERE tu.user_id = 15 AND t.id > 8
I'm trying to write a select statement in MySQL to get 5 rows after I get my match then sum how many times those numbers were repeated.
Example:
Raw Table
id
number
1
1
2
0
3
9
4
14
5
11
6
0
7
3
8
4
9
10
10
9
11
0
12
5
13
3
14
11
15
0
I need to find every row with the number 0, then after that select and show 5 rows after and counting the appearance of the numbers.
How can I select the numbers and get the count as a result?
The result of the first select should be like this:
id
number
3
9
4
14
5
11
6
0
7
3
7
3
8
4
9
10
10
9
11
0
12
5
13
3
14
11
15
0
The result of the count for every number in the last query.
Number
Count
9
2
14
1
11
2
0
3
3
3
4
1
10
1
5
1
This is a demo to get expected results:
Select numbers:
SELECT id, number
FROM (
SELECT b.id, b.number, ROW_NUMBER() OVER(PARTITION BY a.id ORDER BY b.id ASC) r
FROM numbers a
JOIN numbers b ON a.id < b.id
WHERE a.number = 0
) t WHERE t.r <= 5
ORDER BY id
Count numbers:
WITH n AS (
SELECT id, number
FROM (
SELECT b.id, b.number, ROW_NUMBER() OVER(PARTITION BY a.id ORDER BY b.id ASC) r
FROM numbers a
JOIN numbers b ON a.id < b.id
WHERE a.number = 0
) t WHERE t.r <= 5
)
SELECT number, COUNT(*) counts
FROM n
GROUP BY number
Sample data:
CREATE TABLE numbers (
id INT PRIMARY KEY auto_increment,
number INT NOT NULL
);
INSERT INTO numbers ( number ) VALUES (1),(0),(9),(14),(11),(0),(3),(4),(10),(9),(0),(5),(3),(11),(0);
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=1fe71080cfb27680eb2a37b721e5de2d
Update for MySQL v5.7
SELECT n.*
FROM numbers n
JOIN (
SELECT a.id, SUBSTRING_INDEX(GROUP_CONCAT(b.id ORDER BY b.id SEPARATOR ','), ',', 5) selections
FROM numbers a
JOIN numbers b ON a.id < b.id
WHERE a.number = 0
GROUP BY a.id
) t ON FIND_IN_SET(n.id, t.selections)
ORDER BY n.id
SELECT n.number, COUNT(*) counts
FROM numbers n
JOIN (
SELECT a.id, SUBSTRING_INDEX(GROUP_CONCAT(b.id ORDER BY b.id SEPARATOR ','), ',', 5) selections
FROM numbers a
JOIN numbers b ON a.id < b.id
WHERE a.number = 0
GROUP BY a.id
) t ON FIND_IN_SET(n.id, t.selections)
GROUP BY n.number
ORDER BY n.number
https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=3be09acab5cd696ec4b01585eb5c32ed
Selecting the Top n Results, I've seen the numerous posts and great articles on here about how to do it but I am struggling to do it with my data set. Most of the examples focus on data sets without the need for additional joins.
I've been trying to apply the examples from http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/ to my query without much success.
Three tables exist Person, Credit and Media.
Person links to Credit and Credit to Media.
The query below should return the top 5 medias per person, however it doesn't, where have I gone wrong?
SELECT
p.id AS person_id,
c.id AS credit_id,
m.id AS media_id, m.rating_average
FROM person p
INNER JOIN credit c ON c.person_id = p.id
INNER JOIN media m ON m.id = c.media_id
where (
select count(*) from media as m2
inner JOIN credit c2 on m2.id=c2.media_id
where c2.person_id = c.person_id and m2.rating_average >= m.rating_average
) <= 5
Clarification:
Top Medias are calculated from those with the highest rating_average.
Update:
SQLFiddle http://sqlfiddle.com/#!9/eb0fd
Desired output for top 3 medias (m) per person (p). Obviously I would like to do be able this for the top 5 medias but this is only test data.
p m c rating_average
1 9 27 9
1 7 28 8
1 1 1 8
2 1 5 8
2 4 8 8
2 7 29 8
3 4 10 8
3 3 9 6
3 5 11 5
4 3 13 6
4 5 14 5
4 6 15 3
5 4 16 8
5 5 17 5
5 6 18 3
6 6 19 3
7 7 20 8
8 9 23 9
8 1 21 8
8 8 22 0
9 1 24 8
9 7 26 8
9 5 25 5
i think i solve it :)
First here is one solution based on the way you started. But there is a catch I couldn't solve it to show exact 3 (or whatever number you choose i pick 3 for example) row for each person_id. Problem is that solution is based on counting how many rows is there with the rating_average greater then current row. So if you have 5 same top value you could choose to show all 5 or not to show them at all and that's not good. So here is the way you do that... (of course this is example where if you have 4 top value you show them all (I think that no make sense at all to not show the data))...
SELECT t1.person_id, t1.credit_id, t1.media_id, t1.rating_average
FROM (SELECT p.id AS person_id, c.id AS credit_id, m.id AS media_id,
m.rating_average AS rating_average
FROM person p
INNER JOIN credit c ON c.person_id = p.id
INNER JOIN media m ON m.id = c.media_id) as t1
WHERE (SELECT COUNT(*)
FROM (SELECT p.id AS person_id, c.id AS credit_id, m.id AS media_id,
m.rating_average AS rating_average
FROM person p
INNER JOIN credit c ON c.person_id = p.id
INNER JOIN media m ON m.id = c.media_id) AS t2
WHERE t2.person_id = t1.person_id AND t2.rating_average > t1.rating_average) < 3
ORDER BY person_id ASC, rating_average DESC
Important: This solution can work (to show exact 3 rows for each person) if you don't have value that repeat it self... Here is the Fiddle http://sqlfiddle.com/#!9/eb0fd/64 you can see the problem where person_id is 1!
After that i played a little more and make it work just as you wanted in the question i think. Here is a code for that:
SET #num := 0, #person := 0;
SELECT person_id, credit_id, media_id, rating_average, rowNumber
FROM (SELECT t1.person_id, t1.credit_id, t1.media_id, t1.rating_average,
#num := if(#person = t1.person_id, #num + 1, 1) AS rowNumber,
#person := t1.person_id
FROM (SELECT p.id AS person_id, c.id AS credit_id, m.id AS media_id,
m.rating_average AS rating_average
FROM person p
INNER JOIN credit c ON c.person_id = p.id
INNER JOIN media m ON m.id = c.media_id
ORDER BY p.id ASC, m.rating_average DESC) as t1) as t2
WHERE rowNumber <= 3
Here is the Fiddle for that http://sqlfiddle.com/#!9/eb0fd/65 ...
GL!
P. S. sorry for my English hope you could understand what i was talking about...
I have a table for terminal
Id status
1 Online
2 Offline
3 Offline
and I have a separate table where I can find the total hours/date of the up and downtime.
total_time
Id up down
1 10 14
2 20 4
3 15 9
1 5 19
2 4 20
3 10 14
I want to display the terminal id, status and the TOTAL up and downtime(1 = 15(up), 2 = 24(up), 3 = 25(up). I'm using inner join and I have no idea how i will be able to get the sum of the up and downtime..
SELECT terminal.Id, terminal.status, total_time.Id, SUM(total_time.up),SUM(total_time.down)
FROM terminal
INNER JOIN total_time
ON terminal.Id = total_time.Id
WHERE terminal.Id = total_time.Id
Something like this should do the trick. I am interpreting your question as asking for only the sum of the time of the current status. If this is not what you want (and maybe you want the sum of both times), please let me know.
SELECT t.id, t.status, IF(t.status = 'Online', ttlTime.upTime, ttlTime.downTime) as totalTime
FROM terminal t
JOIN
(SELECT tt.id, SUM(tt.up) as upTime, SUM(tt.down) AS downTime
FROM total_time tt
GROUP BY tt.id) ttlTime ON t.id = ttlTime.id
See the SQLFiddle
You get "inner sums" by using the GROUP BY clause.
Try:
SELECT terminal.Id, SUM(total_time.up), SUM(total_time.down)
FROM terminal
INNER JOIN total_time
ON terminal.Id = total_time.Id
GROUP BY terminal.Id
SELECT DISTINCT terminal.Id, terminal.status, total_time.Id, SUM(total_time.up),SUM(total_time.down)
FROM terminal
INNER JOIN total_time
ON terminal.Id = total_time.Id
Should do it. The DISTINCT clause acts as a filter to remove duplicate records from a result set.
Select count(*) as c from casting where ord = 1 Group by actorid Order by count(*) DESC
The result is
15 15 14 13 12 10 7 7 7 7 5 5
Then i would like to get the result only greater than 10 ??how to do that thanks~~
SELECT count(*) AS c
FROM casting
WHERE ord = 1
GROUP BY actorid
HAVING c > 10
ORDER BY c DESC
You can consider HAVING the WHERE clause for GROUP BY aggregates.
SELECT COUNT(*) AS c FROM casting WHERE ord = 1 GROUP BY actorid HAVING COUNT(*) > 10 ORDER BY COUNT(*) DESC
HAVING c > 10
Place this between group by and order by