Table mytable
id numbers whereonly
1 2 1
2 35 1
3 22 1
4 20 1
5 3 1
6 70 1
7 80.15925 1
8 60 7
9 50 7
I need to order by numbers and to take id 1 to search until I found an id that have numbers row bigger with 10.
Desired result: 2, 20, 35, 70, 80.15925
Only where column whereonly is 1
Is there a way to do this?
You can give this a try:
SELECT DISTINCT t1.id AS id, t1.numbers AS numbers
FROM table AS t1
INNER JOIN table AS t2 ON t1.numbers > t2.numbers - 10
WHERE t1.whereonly = 1
GROUP BY t2.numbers
ORDER BY t1.numbers;
Here is the sqlfiddle.
Edit 1: As strawberry suggested
SELECT DISTINCT x.*
FROM mytable x
JOIN
( SELECT t2.numbers t2n
, MIN(t1.id) id
FROM mytable t1
JOIN mytable t2
ON t1.numbers > t2.numbers - 10
GROUP
BY t2.numbers
) y
ON y.id = x.id
ORDER BY x.numbers
WHERE x.whereonly = 1;
Here is the sqlfiddle.
Related
I want select rows from my table with last status_Id if there is a row with status_Id = 2 for that rows
ticketStatus_Id ticket_Id status_Id
======================================
1 1 1
2 1 2 -
3 1 3 *
4 2 1
5 3 1
6 3 2 - *
7 4 1
8 4 2 -
9 4 3
10 4 4 *
I want select just rows 3, 6, 10. there are another rows with status_Id = 2 (rows 2, 6, 8) for that ticket_Id,
In other word How to select rows 3,6,10 with ticket_Id =1,3,4 that there are another row with these ticket_Ids and status_Id=2 (rows 2,6,8)
If you want the complete row, then I would view this as exists:
select t.*
from t
where exists (select 1
from t t2
where t2.ticket_id = t.ticket_id and t2.status_id = 2
) and
t.status_Id = (select max(t2.status_id)
from t t2
where t2.ticket_id = t.ticket_id
);
If you just want the ticket_id and status_id (and not the whole row), I would recommend aggregation:
select ticket_id, max(status_id)
from t
group by ticket_id
having sum(status_id = 2) > 0;
In your case, ticketStatus_Id seems to increase with status_id, so you can use:
select max(ticketStatus_Id) as ticketStatus_Id, ticket_id, max(status_id) as Status_Id
from t
group by ticket_id
having sum(status_id = 2) > 0;
First, for each ticket we get the row with the highest status. We can do this with a self-join. Each row is joined with the row with the next highest status. We select the rows which have no higher status, those will be the highest. Here's a more detailed explanation.
select ts1.*
from ticket_statuses ts1
left outer join ticket_statuses ts2
on ts1.ticket_Id = ts2.ticket_Id
and ts1.status_Id < ts2.status_Id
where ts2.ticketStatus_Id is null
3 1 3
4 2 1
6 3 2
10 4 4
11 5 3
Note that I've added a curve-ball of 11, 5, 3 to ensure we only select tickets with a status of 2, not greater than 2.
Then we can use that as a CTE (or subquery if you're not using MySQL 8) and select only those tickets who have a status of 2.
with max_statuses as (
select ts1.*
from ticket_statuses ts1
left outer join ticket_statuses ts2
on ts1.ticket_Id = ts2.ticket_Id
and ts1.status_Id < ts2.status_Id
where ts2.ticketStatus_Id is null
)
select ms.*
from max_statuses ms
join ticket_statuses ts
on ms.ticket_id = ts.ticket_id
and ts.status_id = 2;
3 1 3
6 3 2
10 4 4
This approach ensures we select the complete rows with the highest statuses and any extra data they may contain.
dbfiddle
This is basicaly a "last row per group" problem. You will find some solutions here. My prefered solution would be:
select t.*
from (
select max(ticketStatus_Id) as ticketStatus_Id
from mytable
group by ticket_Id
) tmax
join mytable t using(ticketStatus_Id)
The difference in your question is that you have a condition requiring a specific value within the group. This can be solved with a JOIN within the subquery:
select t.*
from (
select max(t1.ticketStatus_Id) as ticketStatus_Id
from mytable t2
join mytable t1 using(ticket_Id)
where t2.status_Id = 2
group by t2.ticket_Id
) tmax
join mytable t using(ticketStatus_Id)
Result:
| ticketStatus_Id | ticket_Id | status_Id |
| --------------- | --------- | --------- |
| 3 | 1 | 3 |
| 6 | 3 | 2 |
| 10 | 4 | 4 |
View on DB Fiddle
A solution using window functions could be:
select ticketStatus_Id, ticket_Id, status_Id
from (
select *
, row_number() over (partition by ticket_Id order by ticketStatus_Id desc) as rn
, bit_or(status_Id = 2) over (partition by ticket_Id) > 0 as has_status2
from mytable
) x
where has_status2 and rn = 1
A quite expressive way is to use EXISTS and NOT EXISTS subquery conditions:
select t.*
from mytable t
where exists (
select *
from mytable t1
where t1.ticket_Id = t.ticket_Id
and t1.status_Id = 2
)
and not exists (
select *
from mytable t1
where t1.ticket_Id = t.ticket_Id
and t1.ticketStatus_Id > t.ticketStatus_Id
)
SELECT a.*
FROM t a
JOIN
(
SELECT ticket_id, MAX(status_id) max_status_id
FROM t
WHERE status_id >= 2
GROUP BY ticket_id
) b
ON a.ticket_id = b.ticket_id
AND a.status_id = b.max_status_id;
SELECT
MAX(m1.ticketstatus_Id) as ticket_status,
m1.ticket_Id as ticket,
MAX(m1.status_Id) as status
FROM mytable m1
WHERE
m1.ticket_Id in (select m2.ticket_Id from mytable m2 where m2.ticket_Id=m1.ticket_Id and m2.status_Id=2)
GROUP BY m1.ticket_Id
I have MySQL table as follow:
id p_id c_id
1 11 1
2 11 2
3 11 3
4 12 1
5 12 3
6 13 1
7 13 2
I need a query that when c_id is 1 and 2, it should return 11 and 13 of p_id.
I have tried the following query:
SELECT DISTINCT p_id FROM `Table Name` where c_id in (1,2)
which returns: 11, 12, 13.
but I only need it to return: 11 , 13.
You can write your query as:
SELECT DISTINCT a.p_id
FROM table_name AS a
JOIN table_name AS b ON a.p_id=b.p_id
WHERE a.c_id ='1' AND b.c_id ='2';
It's a self-join on the table itself
SELECT DISTINCT a.p_id
FROM table_name AS a
JOIN table_name AS b ON a.p_id=b.p_id
WHERE a.c_id ='1' AND b.c_id ='2';
it worked fo me
Your query is checking for p_ids related to c_is 1 or 2. But what you want is 1 and 2. You can write this like this:
SELECT DISTINCT t1.p_id
FROM table_name as t1
JOIN table_name as t2
ON t1.id = t2.id
WHERE t1.c_id = 1 AND t2.c_id = 2;
SELECT x.id
FROM my_table x
WHERE other_column IN('a','b')
GROUP
BY x.id
HAVING COUNT(*) = 2;
I have these 2 tables:
table1
uid points
5 13
7 9
12 5
17 3
1 1
2 2
3 1
table2
uid points
9 21
13 17
15 11
17 7
12 6
2 2
1 3
22 1
I need a query to return top 5 users have points
Target result:
uid points
9 21
13 17
5 13
12 11
15 11
What I tried:
select uid, count(points) c from table1 order by c limit 5
union all
select uid, count(points) c from table2 order by c limit 5
But I did not get what I want.
SELECT al.uid as UID , SUM(al.points) AS total_points FROM (SELECT points, uid FROM table1
UNION ALL
SELECT points,uid FROM table2) al group by al.uid
Try This
select uid, (table1.points + table2.points) as c from table1
Left join table2 on table1.uid = table2.uid
order by (table1.points + table2.points) desc limit 5
You can try this query
Select
t3.uid , SUM(t3.points) As points
From
(SELECT * from Table1 UNION ALL SELECT * from Table2) t3
GROUP by
t3.uid
Order by
SUM(t3.points) DESC
LIMIT 5
demo at http://sqlfiddle.com/#!2/5605d/23
Try this:
SELECT Uid,SUM(Points)
FROM
(
SELECT Uid,Points FROM Table1
UNION ALL
SELECT Uid,Points FROM Table2
) as T
GROUP BY Uid
ORDER BY SUM(Points) DESC
LIMIT 5
SQLFiddle demo
If you want the top 5 overall, you need to use an order by and limit over a subquery:
select uid, sum(points) points from (
select uid, points from table1
union all
select uid, points from table2
) x
group by uid
order by sum(points) desc
limit 5
Given the following table ...
ID USER NUM
1 1 69
2 2 75
3 3 7
4 1 31
5 2 18
6 3 70
7 1 12
8 2 23
9 3 42
... which query would return rows with the lowest NUM for each USER?
The result should look like ...
ID USER NUM
7 1 12
5 2 18
3 3 7
Can't wrap my head around this one! Assuming it has a GROUP BY, but everything I try fails... Any pointers?
SELECT t.*
FROM tablename t
INNER JOIN (SELECT user, MIN(num) num
FROM tablename
GROUP BY user) x ON t.user = x.user AND t.num = x.num
or
SELECT t1.*
FROM tablename t1
LEFT JOIN tablename t2 ON t1.user = t2.user AND t1.num > t2.num
WHERE t2.id IS NULL
SELECT ID , MIN(NUM) as MIN_NUM , USER FROM usertable GROUP BY USER
Have a look at demo http://sqlfiddle.com/#!2/ce2fd/1
HEre is another method. UPDATED WITH THE CORRECT REREFERENCE
SQLFIDDLE
Query
select b.id, a.user, a.minnum from
mytable as b
join
(select user, min(num) as minnum
from mytable
group by user
) as a
on b.user = a.user
where b.num = a.minnum
order by a.minnum asc
limit 3
;
Results:
ID USER MINNUM
3 3 7
7 1 12
5 2 18
I have records in two tables as shown below
Table1
userid email
1 123#qwe.com
4 qwe#sdf.cok
5 sad#fgdf.sdf
7 dsvh#dsf.we
9 fdsdf#fgh.hh
.
Table 2
userid values
1 15
1 45
1 76
1 15345
4 4545
4 76788
4 15879
5 4534
5 76345
5 15678
5 4567
5 7667789
7 15
7 456786
7 76678
7 15678
9 45789
9 76789
9 15789
9 4557
9 7667
9 1556
9 4556
9 764
Now I want the first 3 records from table1 with userid in descending order along with the table2 records related to them
SELECT *
FROM (SELECT TOP 3 * FROM Table1) AS Table1 INNER JOIN
Table2 ON Table1.userid = Table2.userid
ORDER BY Table1.userid
SELECT a.userid, a.email, b.values
FROM table1 a
INNER JOIN table2 b ON a.userid = b.userid
ORDER BY a.userid asc
LIMIT 0,3
SELECT * FROM (
SELECT t1.userid, t1.email, group_concat(t2.`values`) as t2values
FROM table1 t1
INNER JOIN table2 t2 ON (t1.userid = t2.userid)
GROUP BY t1.userid
ORDER BY t1.userid ASC
LIMIT 3 ) subselect
ORDER BY subselect.userid DESC
Explanation:
Group_concat is an aggregate function that will make a list of comma separated values.
Because you are using an aggregate function you need to group on userid.
The limit 3 selects the first 3 userid's (because you've ordered ASC)
Then the outer select picks up all 3 rows and reverses the order to DESC.
Links
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat