How can I fetch "partial matches" with mysql? - mysql

I need to find best matches from a mysql table given a set of attributes.
For example, given ATTRIBUTE1, ATTRIBUTE2 and ATTRIBUTE3, I want to get the results as follows:
rows with all attributes matched
rows with 2 attributes matched
rows with 1 attribute matched
so far I only know how to accomplish the first statement:
SELECT * FROM Users
WHERE ATTRIBUTE1="aValue", ATTRIBUTE2="aValue", ATTRIBUTE3="aValue"
LIMIT 20
N.B. I need 2 lists. A list with fully matching rows and a list with partial matches

you can consider to build an composite index in ATTRIBUTE{1..3}
this will benefits for List A
SELECT *
FROM Users
WHERE ATTRIBUTE1="aValue" AND ATTRIBUTE2="aValue" AND ATTRIBUTE3="aValue"
LIMIT 20
and might help some row in List B
SELECT *,
IF (ATTRIBUTE1="aValue", 1, 0) as a1,
IF (ATTRIBUTE2="aValue", 1, 0) as a2,
IF (ATTRIBUTE3="aValue", 1, 0) as a3
FROM Users
WHERE ATTRIBUTE1="aValue" OR ATTRIBUTE2="aValue" OR ATTRIBUTE3="aValue"
ORDER BY (a1+a2+a3) DESC
LIMIT 20

Related

Mysql Select Id in with And operator

I want to get data from table where Id should be as given below in the query but instead of or I would apply and operator so lets say ID IN (5 AND 4 AND 3)
SELECT * FROM table WHERE id IN (5,4,3,1,6)
Is it possible to get data like this.
This is the sample query
SELECT PM.ContentID, PM.Author, PM.Title, PM.Journal, PM.Year, PM.Category, PM.StudyLocation, PM.FileURL from PublishedContentMaster PM join TopicContentMapping T ON T.ContentID=PM.ContentID where PM.ContentID='100' AND T.TopicID IN (16,7)
So I want which is present in both 16 and 17 that is why I need and operator not or.
I suspect that you want an aggregation query and a having clause. It would typically look something like this:
select x
from t
where id in (5, 4, 3, 1, 6)
group by x
having count(*) = 5;
In this case, x would be the column where you want five rows with the five values.

How to find out next available number

In my MySQL table I have field called sequence where I have values like
1 , 2, 3, 5, 6, 7, 8, 10 some of the sequence number are skiped due to deleted records. How do I find out next available number from given number. let's say if I need next number from 3 , how do I get number 5 as my next number in sequence not the 4.
To find out the next ID after 3 that appears in your table, you should do
SELECT id FROM thetable WHERE id>3 ORDER BY id ASC LIMIT 1
This just considers IDs that are greater than 3, in ascending order, and then takes the first one on that list. If it returns you one result, then that's the next one used in the table; if it doesn't return a result at all, then the ID you gave it was already the highest one in the table (or, strictly speaking, at least as high as the highest one in the table).
If you want a general expression that works to get the next available number, then you can use an aggregation query:
select coalesce(max(id), maxid + 1) as NextAvailableId
from table t cross join
(select max(id) as maxid from table t) x
where id > 3;
Or, if you don't like the cross join, you can use conditional aggregation:
select coalesce(max(case when id > 3 then id end), max(id)) as NextAvailableId
from table t;

searching for records in mysql using or - and - not in query

I think I am getting turned around when looking at this. I am trying to get all patron records relating to transactions that have a transaction item with one of a number of ids (1 or 2) as well as transaction items with other ids (3 or 4) but not with transaction items with other ids (5 or 6)
The structure is:
=patron=
id
fname
lname
email
phone
=trans=
id
id_org
id_patron
=trans_item=
id
id_trans
id_perf
I was trying the following:
SELECT
patron.email,
patron.fname,
patron.lname,
patron.phone
FROM
trans_item,
trans,
patron
WHERE
trans_item.id_perf IN (1,2)
AND
trans_item.id_perf IN (3,4)
AND
trans_item.id_perf NOT IN (5,6)
AND
trans_item.id_trans = trans.id
AND
trans.id_org = 1
AND
trans.id_patron = patron.id
GROUP BY
patron.id
ORDER BY
patron.email DESC,
patron.phone DESC
I'm aware that saying the id needs to be 2 AND 4 is always going to return nothing but I need to have it as if id is in (1,2) AND (3,4) so it can be 1 or 2 but also needs to be in 3 or 4
For Clarity:
I am trying to get patrons who have gone to performance 1 OR 2 and 3 OR 4 but NOT 5 OR 6
You can do this with group by and having. The basic idea is:
select ti.id_trans
from trans_item ti
group by ti.id_trans
having sum(ti.id_perf in (1, 2)) > 0 and
sum(ti.id_perf in (3, 4)) > 0 and
sum(ti.id_perf in (5, 6)) = 0;
Each condition in the having clause checks a row for the particular ids. The > 0 means they exist for transaction. The = 0 means they do not.
If you want additional columns from other tables, you can join back to this result set.
I think I have a solution. If I combine the ids for all perfs and group all results by the trans_item.id I can get a list that has duplicates. I then convert them into a php multidimensional array and exclude / include based on the ids for each requirement finding the duplicates that way. Any other suggestions are welcome

mysql query - pairs of repeating numbers

I have a database with 2 columns (ex: no_1, no_2) and then 5000 rows of data, numbers are between 1 - 20 , I need to find a pairs of numbers which where repeating the most of the times?
Any help please ?
Something like this maybe:-
SELECT no_1, no_2, COUNT(*) AS numbercount
FROM SomeTable
GROUP BY no_1, no_2
ORDER BY numbercount DESC

MySQL database resultset with values as close to a number "x" as possible

Im trying to get a result set that contains the 10 values that are closest to, in this case, the number 3.
I have a database that has values in a column named rated which can be 1,2,3,4 or 5. What im trying to do is query the database and return the first 10 rows that have the values closest to 3. The values can be above 3 or below 3. I should note that these values in the rated column are floats.
I then need to sort these rows in order so that rows with value of 3 are first and then the row with lowest offset (+/-) from 3.
Is there any SQL query that can return atleast the result set of values closest to 3 ? or am i going to have to return the whole db and sort it myself?
To get the first 10 rows with highest value down i used the statement
SELECT * FROM tabs ORDER BY 5 DESC LIMIT 10";
5 refers to the column rated
Is there some way to modify this to do what i want ?
Thanks
If I understand your problem correctly, this should do the trick:
select *
from tabs
order by abs(`rated` - 3) asc
limit 10
Note that it sorts by the difference in ascending order, so those with a difference of 0 will come first.
SELECT * FROM tabs ORDER BY ABS(3 - Rate) ASC LIMIT 10
If I got right what you need try:
select *
from (
select
case when -(3-rated) > 0 then -(3-rated) else (3-rated) end as distance,
tabs.*
from tabs
) subsel
order by distance
limit 10