mysql select distinct n row that has a certain value - mysql

Considering here is my table query:
id name number Code
1 red 1 A
2 red 3 B
3 blue 3 C
4 blue 5 A
5 purple 2 D
6 yellow 3 D
7 yellow 4 C
Now I need to query to get 2 random row such that there is 1 name is red and 1 number is 3, kinda like this:
SELECT * FROM table WHERE name = "red" LIMIT 1 and number = 3 LIMIT 1
So like row 1+3,1+6 or 2 + any other row.
Here is my query:
SELECT * FROM table
group by name,number
having count(name="red") = 1
and count(number=3) = 1
ORDER BY RAND()
LIMIT 2;
However, it seems like it just query the row randomly and not satisfying my requirement. Can anyone show me what is wrong ?
Thank you.

I think that this will do what you want:
select t1.*
from tablename t1
inner join (
select t1.id id1, t2.id id2
from tablename t1 inner join tablename t2
on t2.id > t1.id
and ('red' in (t1.name, t2.name)) + ('3' in (t1.number, t2.number)) = 2
order by rand() limit 1
) t2 on t1.id in (t2.id1, t2.id2)
Note that the row with the highest probability to be returned is id = 2, because it can be combined with any other row of the table.
See the demo.

If you can live with odd formatting...
select x.id x_id
, x.name x_name
, x.number x_number
, x.code x_code
, y.id y_id
, y.name y_name
, y.number y_number
, y.code y_code
from my_table x
join my_table y
on y.id <> x.id
where x.name = 'red'
and y.number = 3
order by rand()
limit 1;
https://www.db-fiddle.com/f/6JmLKq1RwaPrSwS3zx4Qmt/0
Previously, I posted this solution, but it too has some flaws, I think. But TB liked it, so I'll keep it here...
select *
from my_table where name = 'red'
union distinct
select *
from my_table where number = 3
order by rand()
limit 2

Related

SQL select rows with number in sequence

I have 1:N table where every entity may have asigned multiple numbers.
ID Number
1 10
1 13
1 11
1 12
1 16
2 11
2 12
2 13
2 10
Now,I want all IDs which have for example 3 numbers in ascending sequence. I do not specify which numbers I want, I just want the SQL to return me all possible combinations it can find but the numbers has to be in ascending sequence and the sequence must contain exactly 3 numbers. The numbers are allways integers of any value. The numbers in result have to be next to each other (12,13,16)is not valid result.
For 3 numbers in this example it would be :
ID 1 : (10,11,12),(11,12,13)
ID 2 : (11,12,13),(10,11,13)
For 2 numbers in this example it would be:
ID 1 : (10,11),(11,12),(12,13)
ID 2 : (11,12)(12,13)
Is this possible in SQL select? Thanx
A solution whats comes close to your expected output.
Involves using self inner joins incombination with CONCAT_WS, GROUP_CONCAT..
For group of three you use this query
Query
SET SESSION group_concat_max_len = ##max_allowed_packet
SELECT
records.ID
, GROUP_CONCAT(CONCAT('(', records.number, ')'))
FROM (
SELECT
DISTINCT
table11.ID
, CONCAT_WS(
','
, table11.Number
, table12.Number
, table13.Number
) AS number
FROM
Table1 AS table11
INNER JOIN
Table1 AS table12
ON
table11.Number + 1 = table12.Number
INNER JOIN
Table1 table13
ON
table12.Number + 1 = table13.Number
ORDER BY
table11.ID ASC
, table11.Number ASC
) AS records
GROUP BY
records.ID
Result
| ID | GROUP_CONCAT(CONCAT('(', records.number, ')')) |
|----|------------------------------------------------|
| 1 | (11,12,13),(10,11,12) |
| 2 | (11,12,13),(10,11,12) |
see demo http://sqlfiddle.com/#!9/c5dfce/39
Simply use join. This produces a result set with each examples of sequential numbers on a different row:
select id, t1.number, t2.number, t3.number
from t t1 join
t t2
on t2.id = t1.id and t2.number = t1.number + 1 join
t t3
on t3.id = t2.id and t3.number = t2.number + 1;
If you really wanted a list, you would simply do:
select id,
group_concat('(', t1.number, ',', t2.number, ',', t3.number, ')') as groups
from t t1 join
t t2
on t2.id = t1.id and t2.number = t1.number + 1 join
t t3
on t3.id = t2.id and t3.number = t2.number + 1
group by t1.id;

how to exclude first and last row if group it on particular id

I have sample table with data like this
id uniqueid values
1 6 0
2 6 1
3 6 2
4 6 0
5 6 1
I want result like this
id uniqueid values
2 6 1
3 6 2
4 6 0
I tried like this
select id,uniqueid,values
FROM t1
WHERE
id not in(SELECT concat(MAX(message_id_pk),',',min(message_id_pk)) FROM t1
where uniqueid=6)
and `uniqueid`=6
GROUP BY uniqueid
but its not working
You can achieve the desired results by doing self join, Inner query will get the the max and min ids for per group and outer query will filter out the results by using minid and maxid
select a.*
from demo a
join (
select `uniqueid`,min(id) minid, max(id) maxid
from demo
where uniqueid=6
group by `uniqueid`
) b using(`uniqueid`)
where a.id > b.minid and a.id < b.maxid /* a.id <> b.minid and a.id <> b.maxid */
Demo
Also you can do it by using 2 sub-queries with EXISTS to exclude the min and max id of each uniqueid.
Query
select `id`, `uniqueid`, `values`
from `your_table_name` t1
where exists (
select 1 from `your_table_name` t2
where t2.`uniqueid` = t1.`uniqueid`
and t2.`id` > t1.`id`
)
and exists(
select 1 from `your_table_name` t2
where t2.`uniqueid` = t1.`uniqueid`
and t2.`id` < t1.`id`
);
Here is a sql fiddle demo
Try this -
SELECT id, uniqueid, values
FROM YOUR_TABLE
WHERE id NOT IN (MIN(id), MAX(id));

SQL Query - Find Duplicates with a Different Key

I have the following data:
id userid name group
1 1 A x
2 1 A y
3 1 A z
4 2 B x
5 2 B y
6 3 C y
7 4 D x
8 5 E x
9 5 E z
10 6 F x
I want to find those records that meet all this condition:
Select all rows where the a userid belongs to a group other than y but the userid also belongs to group y.
The resulting dataset will be as follows:
id userid name group
1 1 A x
3 1 A z
4 2 B x
If you see, it has resulted in two records for userid a because these are two two records belong to groups other than y but the userid 1 also belongs to group y. Same for userid 2.
I have been breaking my head on how to get this in an SQL statement but not even close to a solution.
Any help is appreciated.
Use a join:
SELECT t1.*
FROM mytable t1
INNER JOIN mytable t2
ON t1.user_id = t2.user_id AND t1.group <> t2.group AND t2.group = 'y'
I think that would be the fastest query (but please feel free to try the other solutions as well).
Add an index on user_id if not already there and maybe play with some other indexes as well (maybe a composite index on group and user_id can be utilized)
Use exists
select *
from MyTable a2
where name_group <> 'y'
and exists (select 1
from MyTable a2
where a2.name_group = 'y'
and a2.userid = a1.userid)
You can get all the users that meet the condition using aggregation and having:
select userid
from t
group by userid
having sum( group = 'y' ) > 0 and
sum( group <> 'y') > 0;
I leave it to your to put this into a query to get all the original rows.

How to select random rows where the sum of a column equals to X - MySQL

How i can select random rows of a table when the sum of a column equals to a value ? (MySQL)
Value : 3
Name Price
------------------------
A 1
B 2
C 1
D 3
E 2
I wan to get all possibilities (A + B, D, E + C...).
I have tried to do this :
SELECT * FROM table HAVING SUM(column) = 3 ORDER BY RAND();
Thank's
Thibeault
You need to join the table with itself to get pairs of rows.
SELECT t1.name as name1, t1.price as price1, t2.name AS name2, t2.price AS price2
FROM yourTable AS t1
JOIN yourTable AS t2 ON t1.price + t2.price = 3
ORDER BY RAND()
LIMIT 1

Get Duplicated Count Without Removing

I am trying to get duplicate counts but without actually removing duplicates.
I tried using GROUP BY id and then COUNT(id) but it removes all duplicate entries.
Is there any way to not remove duplicates?
The table looks like this:
ID1 ID2 Value
1 2 someval
1 3 someval
1 4 someval
2 3 someval
2 1 someval
3 1 someval
4 1 someval
I am trying to get this:
ID1 ID2 Value COUNT
1 2 someval 3
1 3 someval 3
1 4 someval 3
2 3 someval 2
2 1 someval 2
3 1 someval 1
4 1 someval 1
I used this:
SELECT ID1, ID2, Value, COUNT(ID1) FROM table GROUP BY ID1;
One of way doing this is to have a separate query for the count and join on it:
SELECT t.id1, t.id2, t.value, cnt
FROM my_table t
JOIN (SELECT id1, count(*) AS cnt
FROM my_table
GROUP BY id1) c ON t.id1 = c.id1
You can do this with a correlated subquery in MySQL;
select id1, id2, value,
(select count(*) from table t2 where t2.id1 = t.id1) as count
from table t;
If performance is an issue then an uncorrelated subquery will likely be orders of magnitude faster than a correlated one...
SELECT x.*
, cnt
FROM my_table x
JOIN
( SELECT id1,COUNT(*) cnt FROM my_table GROUP BY id1) y
ON y.id1 = x.id1;
try something like this :
SELECT YourColumn, COUNT(*) TotalCount
FROM YourTable
GROUP BY YourColumn
HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC