mysql lookup match - mysql

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.

Related

Mysql filter by multiply ids

I can't finish writing query to filter row by multiply ids. Here is query:
select distinct `storage_file`.*, `storage_tag`.`id` as `tid` from `storage_file`
inner join `storage_file_tag` on `storage_file`.`id` = `storage_file_tag`.`storage_file_id`
inner join `storage_tag` on `storage_tag`.`id` = `storage_file_tag`.`storage_tag_id`
where `storage_file`.`user_id` = 17 and `storage_file`.`deleted_at` is null and
`storage_tag`.`id` IN(13,17);
So the result is without group by statement is:
So.. I need result only with two records which contain tid 13 and 17
And when i replace "IN(13,17)" with storage_tag.id = 13 AND storage_tag.id = 17 - i get no records at all
How can i write subquery which will work like a + b but not a OR b ?
I'm not sure what you do exactly but it seams, that the distinct is not working as you expect, because you select "*" from storage_file, as there are different values in the columns of storage_file, the result is distincted but over all selected columnns and so more the two are selected.
You can replace
... AND id IN (11,22)
with
... AND ( id = 11 OR id = 12)
You need the parentheses because WHERE operator precedence rules are very simple.
Of course,
... AND id = 11 AND id = 12
never returns anything because the id cannot have two different values at the same time.

How to get distinct records but on base on first 2 digits only in MySQL

I want to get distinct records (only one field) from a MySQL table, and that field contain only digits.
Example:
00010000
01111100
01112000
01118000
02301201
But distinct records is considered on base on first 2 digits. So in the case above, I need to get back only 3 records:
00010000
01112000
02301201
More over, I would like to trim the rest of the digits, so the actual end result should be:
00
01
02
So distinct and group by will not cut here. Any idea?
Assuming you wanted the least value from among duplicates, you could try:
SELECT t1.col
FROM yourTable t1
INNER JOIN
(
SELECT LEFT(col, 2) AS prefix, MIN(col) AS min_col
FROM yourTable
GROUP BY LEFT(col, 2)
) t2
ON LEFT(t1.col, 2) = t2.prefix AND
t1.col = t2.min_col;
Note: Numbers in MySQL don't start with zeroes, so your requirement (and this answer) only make sense if your column is text.
DISTINCT will work fine with LEFT to give the results you want:
SELECT DISTINCT(LEFT(value, 2)) AS value
FROM data
ORDER BY value
Output
00
01
02
Demo on dbfiddle
If you only want the trimmed value, try this:
SELECT SUBSTRING(yourColumn,1,2) as trimmedval
FROM Table
GROUP BY SUBSTRING(yourColumn,1,2)

SQL calculate the number of row in a specific range

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`;

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.

how to search for a given sequence of rows within a table in SQL Server 2008

The problem:
We have a number of entries within a table but we are only interested in the ones that appear in a given sequence. For example we are looking for three specific "GFTitle" entries ('Pearson Grafton','Woolworths (P and O)','QRX - Brisbane'), however they have to appear in a particular order to be considered a valid route. (See image below)
RowNum GFTitle
------------------------------
1 Pearson Grafton
2 Woolworths (P and O)
3 QRX - Brisbane
4 Pearson Grafton
5 Woolworths (P and O)
6 Pearson Grafton
7 QRX - Brisbane
8 Pearson Grafton
9 Pearson Grafton
So rows (1,2,3) satisfy this rule but rows (4,5,6) don't even though the first two entries (4,5) do.
I am sure there is a way to do this via CTE's but some help would be great.
Cheers
This is very simple using even good old tools :-) Try this quick-and-dirty solution, assuming your table name is GFTitles and RowNumber values are sequential:
SELECT a.[RowNum]
,a.[GFTitle]
,b.[GFTitle]
,c.[GFTitle]
FROM [dbo].[GFTitles] as a
join [dbo].[GFTitles] as b on b.RowNumber = a.RowNumber + 1
join [dbo].[GFTitles] as c on c.RowNumber = a.RowNumber + 2
WHERE a.[GFTitle] = 'Pearson Grafton' and
b.[GFTitle] = 'Woolworths (P and O)' and
c.[GFTitle] = 'QRX - Brisbane'
Assuming RowNum has neither duplicates nor gaps, you could try the following method.
Assign row numbers to the sought sequence's items and join the row set to your table on GFTitle.
For every match, calculate the difference between your table's row number and that of the sequence. If there's a matching sequence in your table, the corresponding rows' RowNum differences will be identical.
Count the rows per difference and return only those where the count matches the number of sequence items.
Here's a query that implements the above logic:
WITH SoughtSequence AS (
SELECT *
FROM (
VALUES
(1, 'Pearson Grafton'),
(2, 'Woolworths (P and O)'),
(3, 'QRX - Brisbane')
) x (RowNum, GFTitle)
)
, joined AS (
SELECT
t.*,
SequenceLength = COUNT(*) OVER (PARTITION BY t.RowNum - ss.RowNum)
FROM atable t
INNER JOIN SoughtSequence ss
ON t.GFTitle = ss.GFTitle
)
SELECT
RowNum,
GFTitle
FROM joined
WHERE SequenceLength = (SELECT COUNT(*) FROM SoughtSequence)
;
You can try it at SQL Fiddle too.