Select range between two columns - mysql

I need query to select value between to columns but one columns have same value
For example :
12 1
12 2
12 3 ------
12 4
12 5
13 1
13 2
13 3
13 4 ------
13 5
i need range to 12 | 3 to 13 | 4
select * from table1 where
((a >= '12' and B >= 2) and (a <= '13' and b <=5))
so the 13 1 is missing :( i have no idea for this query

I think the logic is:
where (a > 12 and a < 13) or
(a = 12 and b >= 3) or
(a = 13 and b <= 4)
Of course, you can also express this more simply using tuples:
where (a, b) >= (12, 3) and
(a, b) <= (13, 4)

this will surely work:
select * from Table1 where
(a=12 and b>=3) or(a=13 and b<=4);
check this up :http://sqlfiddle.com/#!9/7c94ab/6

I think that works:
select * from Test
where (a = 12 and b > 2) or (a = 13 and b < 5);

Related

MySQL overlaping time periods based on criteria

i am trying to write a query which would show me all records which overlap based on values Valid_From and Valid_To and based on criteria.
This is my sample data:
ID | Valid_From | Valid_To | Block_Type | Valid | Block_ID
1 5 10 a TRUE 1
2 10 15 a TRUE 1
3 6 10 a TRUE 1
4 3 4 a FALSE 1
5 2 4 a FALSE 1
6 1 1 a FALSE 1
7 1 10 b TRUE 1
8 1 10 c TRUE 2
9 1 10 c TRUE 2
10 1 15 b TRUE 1
11 5 10 a TRUE 1
ID is Primary Key with Auto Increment - unique for every record
Block_Type - Type of block - can have more values for every Block_ID example: Block_ID 1 has Block_Type "a" and "b", Block_ID 2 has Block_Type "c", every Block_ID can have any Block_Type, meaning every Block_ID can have Block_Type "a" to "z"
Valid - this just states if Valid_To is bigger than some value, for
testing i set this value to 5
Block_ID - groups multiple records in one Group
For showing what records overlap i use this query:
select a.id, GROUP_CONCAT(b.id) as abcd
from new_table a, new_table b
where a.id <> b.id
and a.Block_ID = b.Block_ID
and a.Block_Type = b.Block_Type
and a.Valid = b.Valid
and ((a.Valid_To between b.Valid_From and b.Valid_To) or (a.Valid_From between b.Valid_From and b.Valid_To)
or (a.Valid_To = b.Valid_From) or (a.Valid_From = b.Valid_To))
group by a.id;
this works fine, it shows me if any records with same Block_Type, same value in Valid and Block_ID overlap, my problem is that this query doesnt show me records which dont overlap (in this example it is record with ID 6) i completely understand why, so i tried to edit my query using case when instead of where but so far i wasnt able to achieve what i want.
This is what my query returns now:
ID | abcd
1 2
2 1,11,3
3 2
4 5
5 4
7 10
8 9
9 8
10 7
11 2
I would like this query to list all records and to list in new column "abcd" all overlaping records, for records that do not overlap i would just like null in the same column, so it would look like this:
ID | abcd
1 2
2 1,11,3
3 2
4 5
5 4
6 null
7 10
8 9
9 8
10 7
11 2
cant you point me in the right direction? What can i change to make it work the way i need?
Thank you very much
If i understand your problem correctly, You need a left join instead of Inner join -
SELECT a.id, GROUP_CONCAT(b.id) AS abcd
FROM new_table a
LEFT JOIN new_table b ON a.id <> b.id
AND a.Block_ID = b.Block_ID
AND a.Block_Type = b.Block_Type
AND a.Valid = b.Valid
AND ((a.Valid_To BETWEEN b.Valid_From AND b.Valid_To)
OR (a.Valid_From BETWEEN b.Valid_From AND b.Valid_To)
OR (a.Valid_To = b.Valid_From)
OR (a.Valid_From = b.Valid_To)
)
GROUP BY a.id;

Query within a query to obtain certain value with multiple joins in MySQL Select

I have 3 tables that I have joined in the MySQL query below. All works well EXCEPT I would like the timeadj value with a 1 in column countingtime
to show from table 'data', not the first timeadj value the query finds.
I know this needs to be a query within a query but I am going around in circles and getting no where.
SELECT ttt_entries.tttid, ttt_teams.teamname, data.RacersInTeam,
ttt_entries.CoffeeClass, SEC_TO_TIME(data.timeadj),
COUNT(IF(data.division=5,1,NULL)) 'A+',
COUNT(IF(data.division=10,1,NULL)) A,
COUNT(IF(data.division=20,1,NULL)) B,
COUNT(IF(data.division=30,1,NULL)) C,
COUNT(IF(data.division=40,1,NULL)) D
FROM ttt_entries
INNER JOIN ttt_teams
ON ttt_entries.tttid = ttt_teams.tttid
INNER JOIN (SELECT * FROM data ORDER BY data.countingtime DESC) as data
ON ttt_entries.tttid = data.teamid
WHERE ttt_entries.eventDate = DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE()) >4, -5, 2) + DAYOFWEEK(CURDATE())) * -1 DAY) -- last Thursday
AND data.wtrlid = '22'
GROUP BY ttt_teams.tttid
ORDER BY data.timeadj ASC
For example.... In Team 1 (data.teamid=1) there are 8 time values in timeadj. In the adjacent column (countingtime) is a value either 1 or 0 but only ever 1x 1 per team.
Table ttt_entries
ID tttid CoffeeClass
1 23 Mocha
2 52 Espresso
3 6 Frappe
Table ttt_teams
tttid Name
6 Team A
23 Team 1
52 Team 2
Table 'data'
id wtrlid teamid timeadj countingtime division
1 22 23 3467.123 0 10
2 22 23 3467.125 0 20
3 22 23 3467.432 0 10
4 22 23 3469.000 1 10
5 22 23 3469.112 0 10
6 22 23 3468.987 0 5
My code brings back
tttid teamname RacersInTeam CoffeeClass Time A+ A B C D
23 Team 1 6 Mocha 3467.123 1 4 1 0 0
I need it to bring back the same data but a different time:
tttid teamname RacersInTeam CoffeeClass Time A+ A B C D
23 Team 1 6 Mocha 3469.000 1 4 1 0 0
You can try below way -
SELECT ttt_entries.tttid, ttt_teams.teamname, data.RacersInTeam,
ttt_entries.CoffeeClass, SEC_TO_TIME(max(case when countingtime=1 then data.timeadj end)),
COUNT(IF(data.division=5,1,NULL)) 'A+',
COUNT(IF(data.division=10,1,NULL)) A,
COUNT(IF(data.division=20,1,NULL)) B,
COUNT(IF(data.division=30,1,NULL)) C,
COUNT(IF(data.division=40,1,NULL)) D
FROM ttt_entries
INNER JOIN ttt_teams
ON ttt_entries.tttid = ttt_teams.tttid
INNER JOIN (SELECT * FROM data ORDER BY data.countingtime DESC) as data
ON ttt_entries.tttid = data.teamid
WHERE ttt_entries.eventDate = DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE()) >4, -5, 2) + DAYOFWEEK(CURDATE())) * -1 DAY) -- last Thursday
AND data.wtrlid = '22'
GROUP BY ttt_teams.tttid
ORDER BY data.timeadj ASC

MySQL select a certain amout of rows for each type in a certain c

I would like to select the first certain number of rows, by groups of a certain column. For example :
Original data:
index type value
0 1 a 0.716430
1 2 a 0.223650
2 3 a 0.375417
3 4 a 0.773874
4 5 a 0.802127
5 6 a 0.956563
6 7 b 0.377718
7 8 b 0.487772
8 9 b 0.672767
9 10 b 0.275895
10 11 b 0.981751
11 12 b 0.914780
12 13 b 0.940582
13 14 c 0.347563
14 15 c 0.101106
15 16 c 0.390205
16 17 c 0.235941
17 18 c 0.593234
18 19 c 0.904659
I would like to select the first 4 rows for each unique value of type, and the order is by index.
So the ideal result would be:
index type value
0 1.0 a 0.716430
1 2.0 a 0.223650
2 3.0 a 0.375417
3 4.0 a 0.773874
4 7.0 b 0.377718
5 8.0 b 0.487772
6 9.0 b 0.672767
7 10.0 b 0.275895
8 14.0 c 0.347563
9 15.0 c 0.101106
10 16.0 c 0.390205
11 17.0 c 0.235941
row_number() is the typical solution to this:
select t.*
from (select t.*,
row_number() over (partition by type order by index) as seqnum
from t
) t
where seqnum <= 4;
In older versions of MySQL, you can do:
select tm.*
from telegram_message tm
where tm.index <= coalesce( (select tm2.index
from telegram_message tm2
where tm2.type = tm.type
order by tm2.index asc
limit 1 offset 3
), tm.index
);
The coalesce() is so all rows are taken if there are not 4 rows for the type.
You can get the result you want by self joining your table on index, where the value of index in the joined table is less than that in the first, and selecting only those rows which have < 4 rows with lower index values:
SELECT t1.id, t1.index, t1.type, t1.value
FROM test t1
LEFT JOIN test t2 ON t2.index < t1.index AND t2.type = t1.type
GROUP BY t1.id, t1.index, t1.type, t1.value
HAVING COUNT(t2.index) < 4
Output:
id index type value
0 1 a 0.71643
1 2 a 0.22365
2 3 a 0.375417
3 4 a 0.773874
6 7 b 0.377718
7 8 b 0.487772
8 9 b 0.672767
9 10 b 0.275895
13 14 c 0.347563
14 15 c 0.101106
15 16 c 0.390205
16 17 c 0.235941
Demo on dbfiddle

Select right percentile from joined table

How to select right value from joined table based on the value in more than one column.
I started sqlfiddle: http://sqlfiddle.com/#!9/f92daa/2
Main table:
id val
1 1
2 4
3 67
4 78
5 22
Joined table:
obs_id perc1 perc2 perc3 perc4 perc5 perc6 perc7 perc8 perc9 perc10
1 1 2 3 4 5 6 7 8 9 10
2 1 2 3 4 5 6 7 8 9 10
3 10 20 30 40 50 60 70 80 90 100
4 10 20 30 40 50 60 70 80 90 100
5 10 20 30 40 50 60 70 80 90 100
Expected result should be:
id val perc
1 1 1
2 4 4
3 67 70
4 78 80
5 22 30
perc - should be number from perc table (joined by ids) not greater than highest possible value form columns perc1-10
Table perc stores percentiles of observations. The goal is to find which interval hit the value from main table and take the upper band.
You can use a case expression to do this. This assumes perc1 < perc2 < perc3 < perc4 < ... and so on.
SELECT obs.id, obs.val,
case when val <= perc1 then perc1
when val <= perc2 then perc2
when val <= perc3 then perc3
when val <= perc4 then perc4
when val <= perc5 then perc5
when val <= perc6 then perc6
when val <= perc7 then perc7
when val <= perc8 then perc8
when val <= perc9 then perc9
when val <= perc10 then perc10
end
perc
FROM obs
INNER JOIN perc
ON obs.id = perc.obs_id
SQL Fiddle
If you are sure that perc table will have always the values in ascending order then
select
a.id, a.val,
case
when b.perc1 >= a.val then b.perc1
when b.perc2 >= a.val then b.perc2
when b.perc3 >= a.val then b.perc3
when b.perc4 >= a.val then b.perc4
when b.perc5 >= a.val then b.perc5
when b.perc6 >= a.val then b.perc6
when b.perc7 >= a.val then b.perc7
when b.perc8 >= a.val then b.perc8
when b.perc9 >= a.val then b.perc9
when b.perc10 >= a.val then b.perc10
end as perc
from idval a , perc b
where a.id = b.obs_id

SQL Query, get a columns if another columns equal to x

Lets say I have a table that is like this
x y
10 5
10 8
10 12
11 9
11 14
11 12
14 12
14 5
14 11
I need to return all the x group that has the same value if y = 5
So I would need a query that would return me the x group that has the value 10 or 14.
Query:
select x, y from table ...
Should return me something like this :
x y
10 5
10 8
10 12
14 12
14 5
14 11
select x, y
from your_table
where x in
(
select distinct x
from your_table
where y = 5
)
SELECT *
FROM tableName
WHERE x in
(
SELECT DISTINCT x
FROM tableName
WHERE y = 5
)
SQLFiddle Demo
or a join can also solve it
SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT DISTINCT x
FROM tableName
WHERE y = 5
) b ON a.x = b.x
SQLFiddle Demo