i have the following table and I'm hoping to extract all the unique pairs for ex:
+------+------+
| a | b |
+------+------+
| 1 | 2 |
| 1 | 3 |
| 1 | 6 |
| 1 | 9 |
| 2 | 1 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
| 4 | 1 |
| 6 | 5 |
+------+------+
the out put should be
+------+------+
| a | b |
+------+------+
| 1 | 2 |
| 1 | 3 |
| 1 | 6 |
| 1 | 9 |
| 2 | 3 |
| 6 | 5 |
+------+------+
Try this:
select least(a, b) as a, greatest(a, b) as b
from table t
group by least(a, b), greatest(a, b);
This could produce output that is not in the original table (such as 5/6 instead of 6/5). If you want to preserve the original order:
select distinct a, b
from table t
where a <= b or
not exists (select 1 from table t2 where t2.b = t.a and t2.a = t.b);
That is, select all pairs where a is less than or equal to b or a is greater than b and no row exists with the values in the other order.
SELECT a,b
FROM tbl //your tableName
GROUP BY a,b
HAVING COUNT(*) > 1
try this my friend
SELECT *
FROM NAMES2
GROUP BY Id,id2
HAVING COUNT(*) > 1;
How about this ?
Related
How to make more rows from the table? How to decompress table in MySQL?
+-----+-----------+
| num | frequency |
+-----+-----------+
| 0 | 3 |
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
+-----+-----------+
so that it looks like:
+-----+-----------+
| num | frequency |
+-----+-----------+
| 0 | 3 |
| 0 | 3 |
| 0 | 3 |
| 1 | 1 |
| 2 | 2 |
| 2 | 2 |
| 3 | 1 |
+-----+-----------+
I tried:
SELECT num,
ROW_NUMBER() OVER (PARTITION BY num ORDER BY frequency) AS x
FROM numbers
You could use aa join approach:
INSERT INTO yourTable (num, frequency)
SELECT t1.num, t1.frequency
FROM yourTable t1
INNER JOIN (SELECT 1 AS frequency UNION ALL SELECT 2 UNION ALL SELECT 3) t2
ON t2.frequency < t1.frequency;
You may add more frequency vales to the t2 subquery above as needed.
I have a table like this with 8 rows
+----+------+------+--------+
| id | type | attr1 | attr2 |
+----+------+-------+-------+
| 1 | a | abcd | qwer |
| 2 | a | efgh | tyui |
| 2 | b | ijkl | opas |
| 3 | a | mnop | dfgh |
| 4 | a | qrst | jklz |
| 5 | a | uvwx | xcvb |
| 5 | b | yzab | nmqw |
| 6 | b | cdef | erty |
+----+------+-------+-------+
It is known than type can be either 'a' or 'b'.
I need to select the rows in such a way that if there are more than one rows with same id, then select the one with type 'a'. Else select the row with whatever type is present.
So my desired result should be like
+----+------+------+--------+
| id | type | attr1 | attr2 |
+----+------+-------+-------+
| 1 | a | abcd | qwer |
| 2 | a | efgh | tyui |
| 3 | a | mnop | dfgh |
| 4 | a | qrst | jklz |
| 5 | a | uvwx | xcvb |
| 6 | b | cdef | erty |
+----+------+-------+-------+
I have a MySQL query
SELECT t.id,
CASE
WHEN count(t.id) > 1 THEN 'a'
ELSE t.type
END `type`
FROM table1 t
GROUP BY t.id
ORDER BY t.type ASC
which gives this result
+----+------+
| id | type |
+----+------+
| 1 | a |
| 2 | a |
| 3 | a |
| 4 | a |
| 5 | a |
| 6 | b |
+----+------+
But I need the respective row with all columns.
How to do that?
Note that the MySQL version that I have is 5.7.12.
You don't mention if multiple a's with the same id are possible or what to do in that case. I'm going to assume you want all a rows included. To do that, you just need to exclude b rows when there is a corresponding a row:
select t.*
from table1 t
left join table1 t2 on t2.id=t.id and t.type='b' and t2.type='a'
where t2.id is null;
you also can do it using window function:
select * from
(
select * , row_number() over (partition by id order by case when type = 'a' then 0 else 1 end) rn
) t
where rn = 1;
Hmmm . . . I would be inclined to use not exists:
select t.*
from t
where t.type = 'a' or
not exists (select 1
from t t2
where t2.id = t.id and t2.type = 'a'
);
On table1
+-------+-------+
| unid1 | unid2 |
+-------+-------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+-------+-------+
On table 2
+---------+-------+-------+------+
| tableid | unid1 | unid2 | type |
+---------+-------+-------+------+
| 1 | 1 | 1 | 1 |
| 2 | 2 | 2 | 1 |
| 3 | 3 | 3 | 1 |
| 4 | 3 | 0 | 2 |
| 5 | 3 | 0 | 2 |
| 6 | 4 | 4 | 3 |
| 7 | 5 | 5 | 3 |
+---------+-------+-------+------+
Expected result.
+-------+-------+------+
| unid1 | unid2 | type |
+-------+-------+------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
| 3 | 0 | 2 |
| 3 | 0 | 2 |
+-------+-------+------+
My SQL code
select t1.*, t2.* from table1 t1
left join table2 t2 on t1.unid1 = t2.unid1 and t1.unid2 = t2.unid2 and
t2.type in (1 , 2);
My SQL query does not give the result that i wanted, how can i get the result that i want.
Your expected output implies that you want to retain all rows in table2 whose unid1 values can be found in table1. If so, then we can just inner join these two tables on the unid1 column. This assumes that unid1 is unique in table1.
SELECT t2.unid1, t2.unid2, t2.type
FROM table2 t2
INNER JOIN table1 t1
ON t2.unid1 = t1.unid1;
If I understand you correctly, you want to output values wherein the rows from Table1 matches on Table2 in both columns unid1 and unid2 and that the type must be contained with your desired values.
SELECT b.unid1, b.unid2, b.type
FROM table1 a
INNER JOIN table2 b
ON a.unid1 = b.unid1
WHERE EXISTS
(
SELECT 1
FROM Table1 t1
INNER JOIN Table2 t2
ON t1.unid1 = t2.unid1
AND t1.unid2 = t2.unid2
WHERE t2.type in (1,2)
AND a.unid1 = t1.unid1
)
Here's a DEMO.
I'm looking to allow for a custom ordering logic through mySQL that allows the following data set:
+----+-----------------+------------+-------+--+
| ID | item | Popularity | Views | |
+----+-----------------+------------+-------+--+
| 1 | A special place | 3 | 10 | |
| 2 | Another title | 5 | 12 | |
| 3 | Words go here | 1 | 15 | |
| 4 | A wonder | 2 | 8 | |
+----+-----------------+------------+-------+--+
To return an order that alternates, row by row, by popularity and then by views, so the return results look like:
+----+-----------------+------------+-------+--+
| ID | item | Popularity | Views | |
+----+-----------------+------------+-------+--+
| 3 | Words go here | 1 | 15 | |
| 2 | Another title | 5 | 12 | |
| 4 | A wonder | 2 | 8 | |
| 1 | A special place | 3 | 10 | |
+----+-----------------+------------+-------+--+
Where you will see the first row returns the 'most popular', the second row returns the most views, the third row returns the second most popular, and the 4th row returns the 2nd most views.
Currently I'm gathering an entire table through mySQL twice, and then merging these results in PHP. This isn't going to cut it when the database is large. Is this possible in mysql at all?
I guess something along these lines could work. Consider the following:
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,x INT NOT NULL
,y INT NOT NULL
);
INSERT INTO my_table VALUES
(1,3,10),
(2,5,12),
(3,1,15),
(4,2, 8)
(5,4, 1);
We can rank x and y in turn, and then arrange those ranks in a single list - so will have x1,y1,x2,y2,etc - but all rows will appear twice; once for the x rank and once for the y rank...
SELECT * FROM
(
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.x <= a.x GROUP BY a.id )
UNION ALL
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.y <= a.y GROUP BY a.id )
) n
ORDER BY rank
+----+---+----+------+
| id | x | y | rank |
+----+---+----+------+
| 5 | 4 | 1 | 1 |
| 3 | 1 | 15 | 1 |
| 4 | 2 | 8 | 2 |
| 4 | 2 | 8 | 2 |
| 1 | 3 | 10 | 3 |
| 1 | 3 | 10 | 3 |
| 5 | 4 | 1 | 4 |
| 2 | 5 | 12 | 4 |
| 2 | 5 | 12 | 5 |
| 3 | 1 | 15 | 5 |
+----+---+----+------+
Now we can just grab the lowest rank for each id...
SELECT id
, x
, y
FROM
(
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.x <= a.x GROUP BY a.id )
UNION ALL
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.y <= a.y GROUP BY a.id )
) m
GROUP
BY id,x,y
ORDER
BY MIN(rank);
+----+---+----+
| id | x | y |
+----+---+----+
| 3 | 1 | 15 |
| 5 | 4 | 1 |
| 4 | 2 | 8 |
| 1 | 3 | 10 |
| 2 | 5 | 12 |
+----+---+----+
Incidentally, this should be faster with variables - but I cannot make that solution work at present - senior moment, perhaps.
Given the following data set, I want to select the rows (all columns) comprised between the first one and the last of the result of selecting 'n' distinct on col1 and col2.
pkey | col1 | col2 | day | Other columns...
1 | a | 1 | 1 |
2 | b | 2 | 1 |
3 | b | 2 | 1 |
4 | c | 3 | 1 |
5 | c | 4 | 1 |
6 | a | 5 | 2 |
7 | a | 5 | 2 |
8 | b | 6 | 2 |
9 | c | 7 | 2 |
10 | c | 8 | 2 |
For n = 5, the result must be:
pkey | col1 | col2 | day | Other columns...
1 | a | 1 | 1 |
2 | b | 2 | 1 |
3 | b | 2 | 1 |
4 | c | 3 | 1 |
5 | c | 4 | 1 |
6 | a | 5 | 2 |
7 | a | 5 | 2 |
I am trying by using SELECT DISTINCT col1, col2 FROM sampletable as a base but then I have no access to the other columns. How could this be achieved?
Edit:
Changed description to be more clear regarding what I want
Changed col2 of rows 6 and 7 from 1 to 5 to be closer to my real data.
SELECT a.*
FROM sampletable AS a
INNER JOIN (SELECT DISTINCT col1, col2 FROM sampletable LIMIT 5) AS b
ON a.col1 = b.col1 AND a.col2 = b.col2
Select a.* from sampletable a inner join (
SELECT MIN(pkey) as pkey FROM sampletable GROUP BY col1,col2 limit 5) b on a.pkey = b.pkey
Use this query.
Another different way:
SELECT DISTINCT(CONCAT(col1, col2)) AS fgroup, pkey, day... FROM [table] GROUP BY fgroup LIMIT [LIMIT]
Replace [table] by your table name.
Replace [limit] by the desired limit.
Replace the "..." by all the extra fields that you want to list.