SQL calculate the number of row in a specific range - mysql

There's two table in my database:
Table A
Column_A1 column_A2
A1 10
A2 20
A3 30
Table B
Column_B1 column_B2
B1 11
B2 21
B3 31
B4 29
B5 30.5
I want to calculate how many row of table B match the following condition:
range:
A1±1,
A2±1,
A3±1,
...
for example:
B1∈[A1-1,A1+1]
count these row, return value 1.
B2∈[A2-1,A2+1]
count these row, return value 1.
B3∈[A3-1,A3+1]
B4∈[A3-1,A3+1]
B5∈[A3-1,A3+1]
count these row, return value 3.
Result should be like this:
Column_A1 column_A2 num_match
A1 10 1
A2 20 1
A3 30 3
It's easy to use a loop to do this in other programming language, but what's the simplest way to make it in SQL ? Thanks.

I would do this with a correlated subquery:
select a.*,
(select count(*)
from b
where b.column_b2 between a.column_a2 - 1 and a.column_a2 + 1
) as num_match
from a;
Note: between is used suggesting that the bounds are included in the range. If this is not the intention, then use explicit < and > logic.
Many databases would be able to take advantage of an index on b(column_b2) for this query. You can test on MySQL to see if this is the case.

You can use a GROUP BY statement and filter on inequalities:
SELECT Column_A1,Column_A2,COUNT(*)
FROM A JOIN B ON column_A2-1 <= column_B2 AND column_B2 <= column_A2+1
GROUP BY Column_A1,Column_A2

A simple query that matches with the way the OP expressed the goal of the statement:
SELECT
a.`Column_A1`,
COUNT(*) as `NumMatch`
FROM `Table_A` a
JOIN `Table_B` b
ON b.`column_b2` BETWEEN a.`column_A2` - 1 AND a.`column_A2` + 1
GROUP BY a.`Column_A1`;

Related

SQL query statement Self Join?

new to SQL.
I have the following set of data
A X Y Z
1 Wind 1 1
2 Wind 2 1
3 Hail 1 1
4 Flood 1 1
4 Rain 1 1
4 Fire 1 1
I would like to select all distinct 'A' fields where for all rows that contain A have flood and rain.
So in this example, the query would return only the number 4 since for the set of all rows that contain A = 4 we have Flood and Rain.
I need the values of A where for a given value 'a' in A, there exists rows with 'a' that must contain all of the following fields provided (in the example Flood and Rain).
Please let me know if you need further clarification.
I need the values of A where for a given value 'a' in A, there exists rows with 'a' that must contain all of the following fields provided (in the example Flood and Rain).
You can use aggregation, and filter with a having clause:
select a
from mytable t
where x in ('Flood', 'Rain') -- either one or the other
having count(*) = 2 -- both match
If tuples (a, x) tuples are not unique, then you want having count(distinct x) = 2 instead.
You Shooud use count(distinct X) group by A and having
count(distinct...) avoid situation where you have two time the same value for X
select A
from my_table
WHERE x in ('Flood', 'Rain')
group A
having count(distinct X) = 2

For Loop in MySQL, looping through a table and applying it to a where statement

My problem is how to loop through a table and extract information from another table.
I have a table - X with 470 records:
A B C
111 12 18
121 21 29
127 37 101
I would like to write the following query:
create or replace view NEW as
For j = 1-3
Select * from Y
where imei = X.A(j) and id > X.B(j) and id < X.C(j)
Apologies, I am a matlab programmer so I have used that syntax above to explain what I want. How can I do this in MySql? I have looked up For Loops but mostly it loops through within the same table. I need to loop through a different table and use those criteria in the where statement of a different table.
To get 3 rows from a table, use LIMIT 3 in a subquery. To get related rows in another table, use JOIN.
CREATE OR REPLACE VIEW new AS
SELECT Y.*
FROM Y
JOIN (SELECT *
FROM X
LIMIT 3) AS X ON Y.ime1 = X.a AND Y.id > X.b AND Y.id < X.c
To make LIMIT 3 produce predictable results, you should have an ORDER BY clause in the subquery. Otherwise, it will select an arbitrary set of 3 rows from X.

Collect all non-numeric values from a column after GROUP BY clause in MYSQL

I have a MySQL Table that defines causality relation between the columns. Here Event_B happens because of Event_A. Any value present in Event_A is not present in Event_B for that Row_ID.
Row_ID Event_A Event_B
-------------------------
1 A1 B1
2 A2 B3
3 A1 B2
4 A4 A1
When considering A1 from Event_A, its values will be all those values from Event_B {B1, B2}, but shall never include A1 in any case.
The values in the Event_A and Event_B columns are repetitive.
On applying GROUP BY clause on Event_A, I would like to collect all values of Event_B column for that respective Event_A into a variable/collection/set.
Need some directions on SQL Scripts to proceed ahead.
[EDIT]:
The solution would be like :
A1 -- {B1, B2}
A2 -- {B3}
A4 -- {A1}
Do you just want group_concat()?
select event_a, group_concat(event_b) as event_bs
from table t
group by event_a;
Try this:
SELECT Event_A, GROUP_CONCAT(Event_B)
FROM your_table
GROUP BY Event_A;

Counts where more than one column is true

I have a table with 7 true/false columns, how can I select ALL rows that have 2 or more of the columns set to true?
Here is what I have so far:
select count(*), c1,c2,c3,c4,c5,c6,c7
from members
where
1 in (c1,c2,c3,c4,c5,c6,c7);
A true/false column is just a 1 digit integer. Unless you have values other than 0 and 1 stored or the column is nullable, you can just add the columns and check whether the result is >= 2
SELECT * FROM members WHERE c1 + c2 + c3 + c4 + c5 + c6 + c7 >= 2
If there are some non-0 and non-1 entries, you should correct this beforehand. If they can be NULL, you'll need to use WHERE IFNULL(c1, 0)...
You could try following:
SELECT * FROM members WHERE c1+c2+c3+c4+c5+c6+c7>=2
Since true is 1, you can calculate the total of the fields to be more => 2.
SELECT * FROM members WHERE c1+c2+c3+c4+c5+c6+c7 >= 2

mysql lookup match

I have a database column like this:
id
50
55
56
62
63
64
65
68
70
72
80
etc...
I want to iterate through the id column with the following formula to find if the result of the formula is an id number in the same column. I want to compute all the possible combinations of the set of basically 3 records in the id column.
First loop:
Does ((second_id_number - first_id_number) * variable decimal) + second_id_number equal a number in the id column?
Per the formula, the first loop is
(55-50)*2.00(as an example of variable decimal) + 55 = 65. 65 is in the list => 65 is tagged with the 2 records which equal it
Second loop:
Does ((third_id_number - first_id_number) * variable decimal) + second_id_number equal a number in the id column?
(56-50)*2.00(as an example of variable decimal) + 56 = 78. 78 is not in the list => 78 is not tagged
Third loop:
Does ((fourth_id_number - first_id_number) * variable decimal) + second_id_number equal a number in the id column?
etc...
I want the results to show all the tagged records. A tagged record is the set of the 3 records where the third record is the result from the formula.
Anyone got any ideas? Is it possible in mysql?
Thank you
If I'm understanding your requirements properly, it sounds like you'd want to use a self-join on the table, e.g.
SELECT ...
FROM yourtable AS parent
LEFT JOIN yourtable AS child ON
FLOOR((parent.second_id_number - parent.first_id_number) * variable) + parent.second_id) = child.id
You could potentially carry something like this forward, which satisfies your first "loop"
select a.id as first_id_number
, b.id as second_id_number
, ((b.id - a.id) * 2) + b.id as third_id_number
from my_table as a
join my_table as b on a.id = (select max(id) from my_table where id < b.id)
where ((b.id - a.id) * 2) + b.id in (select id from my_table)
According to your description and test data, this would show 65 as "tagged" with first_id_number 50 and 62.
Warning: done on SQL Server using what I think is fairly standard syntax. I would understand if some would rather phrase this as a cross join with the select max... bit in the where clause rather than in the join predicate.