MySQL query: help needed - mysql

I have two integer columns in a table where the first column is populated with some random numbers and the second column is empty. Now is it possible to sort the first column in ascending order and at the same time sort it in descending order and display as the second column? I have the example of the table below.
Initial Table:
col1 col2
5
7
3
9
2
Output:
col1 col2
2 9
3 7
5 5
7 3
9 2

Try this:
SELECT tb1.col1,tb2.col2 FROM
(SELECT #rownum:=#rownum+1 as rank, id as col1
FROM your_table, (SELECT #rownum:=0) as r
ORDER BY id ASC) as tb1
JOIN
(SELECT #rownum2:=#rownum2+1 as rank, id as col2
FROM your_table, (SELECT #rownum2:=0) as r
ORDER BY id DESC) as tb2
ON tb1.rank = tb2.rank

Related

SELECT 2 rows of the same column value

I have data that looks like
id val
--------
1 1
2 1
3 1
4 2
5 2
6 2
7 3
8 3
9 3
I'd like to fetch the id (and value) of two randomly chosen rows for each value, something like:
id val
--------
2 1
3 1
4 2
6 2
8 3
9 3
[EDIT]
I use MySQL v5.7
[SOLUTION]
I finally found another solution to my problem which is more compact and more useful if for example I want to limit the results to 25 id per value
SELECT val, SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY RAND() SEPARATOR ','), ',', 2)
FROM my_table
GROUP BY val
The idea is to group by val, concatenate the corresponding id in a string and taking a substring of the desired length.
try this
SELECT t.val,
#id := (SELECT t2.id FROM tbl_values t2 WHERE t2.val=t.val ORDER BY RAND() LIMIT 1) id1,
(SELECT t2.id FROM tbl_values t2 WHERE t2.val=t.val and t2.id<>#id ORDER BY RAND() LIMIT 1) id2
FROM tbl_values t
GROUP by 1
db fiddle demo
With MySQL 8.0 you could use ROW_NUMBER():
SELECT id, val
FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY val ORDER BY RAND()) AS rn
FROM tab) sub
WHERE rn <=2;
DB-Fiddle.com Demo
How about something like:
SELECT val, MIN(id)
FROM data
GROUP BY val

get number of occurrences between two columns same table

I have a problem on how to fetch the number of occurrences of a value in between two columns in MySQL.
id1 col1 col2
2 5 3
3 3 4
4 2 1
5 1 3
6 null 2
How am I able to get the number of occurences between the two columns like the following?
value occurrence
3 3
1 2
2 2
4 1
5 1
You could union all the columns and then apply a count aggregate function:
SELECT val, COUNT(*) AS occurrence
FROM (SELECT col1 AS val
FROM mytable
UNION ALL
SELECT col2 AS val
FROM mytable) x
GROUP BY val
ORDER BY occurrence DESC
Depending on the actual data (number of rows per value) pre-aggregating might be more efficient, simply try it out:
SELECT val, SUM(occurrence) AS occurrence
FROM (SELECT col1 AS val, COUNT(*) AS occurrence
FROM mytable
UNION ALL
SELECT col2 AS val, COUNT(*) AS occurrence
FROM mytable) x
GROUP BY val
ORDER BY occurrence DESC

Select conditionally limited data from a single table

There is a table of the form:
t_news
id
title
cat
Categories are not consistent for each news. That is, it may be first 2 news first category, then a third, then a fifth, etc.
Need to get to 5 news every category, sorted by date.
What is the output should be similar to the following (example, 3 news, Category 3)
id title cat
1 News1 1
2 News2 1
3 News3 1
4 News4 2
5 News5 2
6 News6 2
7 News7 3
8 News8 3
9 News9 3
In MySQL you can use variables to create a row number column:
SELECT id, title, cat
FROM ( SELECT id,
title,
cat,
#r:=IF(#cat = cat, #r+1, 1) AS RowNum ,
#cat:= cat AS Cat2
FROM t_news,
(SELECT #cat:= 0) AS cat,
(SELECT #r:= 0) AS r
ORDER BY cat, id
) t
WHERE RowNum <= 5;
The key is at each row if the cat column is the same as the #cat variable (set from the previous row), then the row number increments by one. Otherwise it resets to 0. The order of the increment is set by the order by clause in the subquery (I have used ID since the schema you posted does not include a date column).
Example on SQL Fiddle
Total code:
SELECT id, title, cat, from_unixtime(date) `date` FROM (
SELECT id, title, cat, `date`
FROM
(
SELECT id, title, cat, `date`, #r:=IF(#cat = cat, #r+1, 1) AS RowNum , #cat:= category AS Cat2
FROM news, (SELECT #cat:= 0) AS cat, (SELECT #r:= 0) AS r
WHERE hide=0
ORDER BY cat, `date` DESC, id
) t
WHERE RowNum <= 4 LIMIT 16
) t2
ORDER BY `date` DESC;
#GarethD, Thank you =)

Need a sequence number for every row in MySQL query

So I found this great use:
SELECT (#row:=#row+1) AS ROW, ID
FROM TableA ,(SELECT #row := 0) r
ORDER BY ID DESC
The #row:=#row+1 works great, but I get the row ordered by the ID.
My tables look more like this:
SELECT (#row:=#row+1) AS ROW, ID , ColA, ColB, ColC
FROM TableA
JOIN TableB on TableB.ID = TableA.ID
JOIN TableC on TableC.ID = TableA.ID
WHERE ID<500
,(SELECT #row := 0) r
ORDER BY ID DESC
Note:
I noticed that if I remove the JOINs I DO get the requested result (In Which ROW is the sequential number of each row, no matter the ORDER BY of ID). The first example works great but for some reaosn, the JOINs mess it up somehow.
so I get this:
ROW | ID
3 15
2 10
1 2
What I am after is:
ROW | ID
1 15
2 10
3 2
Here's the SqlFiddle
So it basically seems that the row number is evaluated before the ORDER BY takes place. I need the ORDER BY to take place after row was given.
How can I achieve that?
Remove the ORDER BY:
SELECT (#row:=#row+1) AS ROW, ID
FROM table1 ,(SELECT #row := 0) r
See SQL Fiddle with Demo
Then if you want to use an ORDER BY wrap the query in another SELECT:
select *
from
(
SELECT (#row:=#row+1) AS ROW, ID
FROM table1 ,(SELECT #row := 0) r
) x
order by row
Or if you leave the ORDER BY on the query, then you can see the way the row number is being applied by simply playing with either DESC or ASC order - See Demo
If you use DESC order
SELECT (#row:=#row+1) AS ROW, ID
FROM table1, (SELECT #row := 0) r
order by id desc;
the results are which appears to be the result you want:
ROW | ID
----------
1 | 15
2 | 10
3 | 2
If you use ASC order:
SELECT (#row:=#row+1) AS ROW, ID
FROM table1 ,(SELECT #row := 0) r
ORDER BY ID;
the results are:
ROW | ID
----------
1 | 2
2 | 10
3 | 15
Edit, based on your change, you should place the row number in a sub-query, then join the other tables:
select *
from
(
SELECT (#row:=#row+1) AS ROW, ID
FROM Table1,(SELECT #row := 0) r
order by ID desc
) x
JOIN Table2
on x.ID = Table2.ID;
See SQL Fiddle with Demo
I dont find any problem with your query
SELECT (#row:=#row+1) AS ROW, ID
FROM table1 ,(SELECT #row := 0) r
order by ID desc
SQL Fiddle demo

Mysql query random order (pause and continue) question

Okay i am trying to create a mysql query that does this:
show 3 random records from table then after the 3th record show TEXT
and then show the same 3 items but other field (equaling to the items ofcourse) from same table.
eg table info:
--ids | titles------
10 | one
20 | two
30 | three
and the query results from the given example:
30 10 20 TEXT three one two
if anyone understand what i am asking,post your suggestion/asnwer
thanks for your time all :)
Just for kicks..
select t1.id, t2.id, t3.id, 'TEXT', t1.title, t2.title, t3.title
FROM
(
select #r := #r + 1 rownum, id
from (select #r:=0) initvar, (
select id
from tbl
order by rand()
limit 3
) X
) Y
join tbl t1 on Y.rownum=1 and t1.id = Y.id
join tbl t2 on Y.rownum=2 and t2.id = Y.id
join tbl t3 on Y.rownum=3 and t3.id = Y.id
You should really just do the query below, and do whatever display processing using the 3 rows returned, in whatever programming environment you use (Java/PHP/.Net etc).
select id, title
from tbl
order by rand()
limit 3
EDIT
To get the data in 7 different rows, you can use the below. I stress again that this is front-end display code. I will not use such SQL code in a production system.
select display
from
(
select sorter, rownum,
case when sorter=3 then title else id end display
from
(
select #r := #r + 1 rownum, id, title
from (select #r:=0) initvar,
(
select id, title
from tbl
order by rand()
limit 3
) X
) Y, (select 1 sorter union all select 3) dup
union all
select 2, 0, 'TEXT'
) Z
order by sorter, rownum
Example Output
7
2
1
TEXT
test 7 << title for id=7
test 2
test 1