How to find the nearest row based on two integer columns? - mysql

Here is a MySQL table, which has three rows.
ram cpu
1 2
4 8
8 16
if I give input as ram=7 and cpu=9,
the query has to smartly select the closest row based on the two input values and return me a single row.
example result which I expect for 7,9 combination:
ram cpu
4 8
is this possible to achieve?
Consider me having thousands of combinations like this. I need a query that always smartly returns a single row.

You never gave us an exact heuristic for what "closest" means, given that there are two columns involved. Assuming you can accept the record whose sum of absolute difference from the two input values in smallest, then here is one way:
SELECT ram, cpu
FROM yourTable
ORDER BY
ABS(ram - 7) + ABS(cpu - 9)
LIMIT 1;
Demo

Related

How to select two MySQL rows and then compare a column and return an output

I've a table with a structure something like this,
Device | paid | time
abc 1 2 days ago
abc 0 1 day ago
abc 0 5 mins ago
Is it possible to write a query that checks the paid column on all the rows where Device = abc and then outputs the most recent two rows that different. Basically, something like an if statement saying if row 1 = 1 and row 2 = 0 output that but only if it's the most recent two columns that are different. For example, in this case, the first and second row. The table is being updated whenever a user changes from a free to paid account etc. It is also updated in different columns for different reasons hence the duplicate 0s for example.
I know this would probably be done better by having another table altogether and updating that every time the user switches account type, but is there any way to make this work?
Thanks
Example:
http://rextester.com/MABU7860 need further testing on edge cases but this seems to work.
SELECT A.*, B.*
FROM SQLfoo A
INNER JOIN SQLFoo B
on A.Device = B.Device
and A.mTime < B.mTime
WHERE A.Paid <> B.Paid
and A.device = 'abc'
ORDER BY B.mTime Desc, A.MTime Desc
LIMIT 1
By performing a self join we on the devices where the time from one table is less than the time from the next table (thus the two records will never matach and we only get the reuslts one way) and we order by those times descending, the highest times appear first in the result since we limit by a single device we don't need to concern ourselves with the devices. We then just need compare the paid from one source to the paid in the 2nd source and return the first result encountered thus limit 1.
Or using user variables
http://rextester.com/TWVEVX7830
in other engines one might accomplish this task by performing the join as in above, assigning a row number partitioned by the device and then simply return all those row_numbers with a value of 1; which would be the earliest date discrepency.
Use LIMIT to limit the number of record on mysql:
http://www.mysqltutorial.org/mysql-limit.aspx
In your case, use LIMIT 2
and then put the 2 record that you just select into an array, then compare the array if the value is different. If they are different then print

Need to find whether overlap is present in sql

I haev been stuck in a problem from quite some time and trying to figure out how to solve this using sql.
I have a table which has 3 columns :
LowerLimit UpperLimit Code
1 10 A
10.01 20 B
20.01 40 C
40.01 100 D
So in such case I need to check if there overlap present or not. The Upperlimit should not match with the LowerLimit of the next row and the permissible difference is only 0.01 . Is it possible to solve this using queries or do I need to iterate the whole range and find whether there is no overlap???
Any help is appreciated.
You can do this with exists to get the first row of overlap. For your specific logic:
select t.*
from t
where exists (select 1
from t t2
where t2.upperlimit >= t.lowerlimit and
t2.upperlimit < t.upperlimit + 0.01
);
If you want both rows, you can formulate this as a join or using a second exists to get the previous row.
I don't like your data representation. I would simple make the lower bound inclusive and the upper bound exclusive. Then the next lower bound could simply be the previous upper bound. You would not be able to use between but that is a bad idea anyway on numbers with decimal parts.

mysql find rows with fractional part of number

Using the MySQL command prompt, I want to SELECT all rows conataining a specific fractional part of number.
I have a field of type FLOAT called priority & I want to find all rows where the priority is X.2 where X can be any whole number.
Is there a way to use the MOD or FLOOR function to extract the ".2" in a query?
I've tried:
SELECT * from table
WHERE priority-FLOOR(priority) = .2 *(note the decimal point before the 2)*
but it returns empty set when I know there are at least 100 rows containing a priority of X.2
Thanks
What about using the LIKE clause in MySQL?
SELECT * FROM table WHERE priority LIKE %.2%
Floating point numbers are notoriously fickle to work with. That is why SQL offers the decimal data type, which is fixed length.
Do what you want with between:
SELECT *
from table
WHERE priority-FLOOR(priority) between 0.15 and 0.25
Consider storing the priority as a decimal instead of a floating point number.
If you have "deeper" priorities, like 1.22 that you are trying to avoid, then do:
WHERE priority-FLOOR(priority) between 0.195 and 0.205
The range can be even narrower, if you need.

"Sparse" Rank in Business Objects XI Web Intelligence?

In Business Objects XI Web Intelligence the Rank function returns dense results. For example when ranking by "Amount" I want to return the top ten records only. However three records tie for 5th place on "Amount". Result is a total of 12 records: one each for places 1 to 4 and 6 to 10 and 3 records for 5th place.
Desired result is a "sparse" top ten that drops the two lowest ranked records (places 9 and 10).
I tried to do this and rank customers by amount.
I have 2 objects: [Amount] and [Customernumber].
[Customernumber] is numeric.
I created a new variable:
[varForSorting]=[Amount]*10000000+ToNumber([Customernumber])
Then I rank by the new variable [varForSorting].
Customers with the same Amount will be sorted in Alphabetic order by Customer number. I hope this helps.
Here is an example of how I solved it for a change in Account Count over time. This approach allows you to break your dense rank ties using other measures in your data provider. Basically you use multiple measures in one rank and decide which measure to rank by first, second, etc:
Step 1: Determine the change amount
v_Account_Count_Delta_Amount
=([v_Account_Count_After] - [v_Account_Count_Before])
Step 2: Rank the change amounts (this is where ties and dense rank cause multiple rows to be returned)
v_Account_Count_Delta_Amount_Rank
=NoFilter(Rank([v_Account_Count_Delta_Amount]))
Step 3: Compute the tie breaking rank using other measures
v_MonthToDateMeasuresRank
=NoFilter(Rank([Month To Date Sva]+ [Bank Share Balance] + [Total Commitment]))
Step 4: Compute a combined rank that is now free from ties and weight your ranks however you choose
v_Account_Count_Combined_Rank
=Rank([v_Account_Count_Delta_Amount_Rank]* 1000000 + [v_MonthToDateMeasuresRank];Bottom)
Step 5: Filter your data block for v_Account_Count_Combined_Rank <= 10
Ultimately depending on your data it could still result in a tie unless you take the additional step of ranking by some other unique attribute that you can turn to a number (see Maria Ruchko's answer for that bit of magic using Customer Number). I tried to do that with RowIndex() and LineNumber() but could not get usable results. My measures when added together happen to never tie so this works for my specific data blob.

MySQL group multiple(variable) rows into one row with multiple columns

I'm looking for a query that will return me several rows into columns but without knowing the number of rows beforehand. I have searched and the only solutions I found involve knowing how many rows there are.
Here's an example table:
parentID colA colB
2 aaaaaa 1000.00
2 bbbbbb 1500.00
3 cccccc 500.00
3 dddddd 700.00
3 eeeeee 2000.00
and i need it to look like:
parentID colA(n) colB(n) colA(n+1) colB(n+1) colA(n+2) colB(n+2)
2 aaaaaaa 1000.00 bbbbbb 1500.00 NULL NULL
3 cccccc 500.00 dddddd 700.00 eeeeee 2000.00
I realize this should be done in PHP but I need it to be in mysql for a third party excel exporter plugin I'm using.
Edit: Is there a way to do this if I know the maximum number of columns I'll need?
You cannot do a query in SQL without knowing the number of columns.
The columns of a SELECT-list must be fixed at the time of parsing the query. What you're asking for is that the state of data, which is not known until the query executes, determines the number of columns. That is not the way SQL works.
To accomplish a pivot-type operation, or any query where the data determines the columns, you have two choices:
Do a preparatory query to discover how many distinct groups you want to fetch, and use this to build the query with a matching number of columns.
Query all the data in rows, fetch it back into your application, and then transform the result set wholly within data structures (i.e. arrays) within your code.
Either way, you need to write application code, either before or after fetching the data.
Re your comment: You're right, this isn't a traditional pivot, but it's similar in that data is driving the number of columns. That is, you need as many columns as 2x the number of rows in the largest group. But they won't all be filled, because the number of rows per group varies. You don't have a fixed number of row per group, therefore you can't fill a fixed number of columns per group.
I'd really recommend you use the latter strategy: fetch the data as rows, as they are stored in the database. Then post-process it in your application code. Loop over the result set and build your data structure incrementally as you fetch rows from the database.
For example, in PHP:
while ($row = $stmt->fetch()) {
$data[$row['parentID']][] = $row['colA'];
$data[$row['parentID']][] = $row['colB'];
}