How to select different rows from 2 tables - mysql

I'am trying to get randomly 3 different rows from 2 tables with different fields
SELECT * FROM `models` JOIN banners WHERE `recomended` = '1' ORDER BY RAND() LIMIT 0,3
I want a result like this:
first row - table1.id table1.name table1.points
second row - table2.id table2.group table.2points
third row - table1.id table1.name table1.points
is that possible to do?

Here is one way to get what you want:
select id, name, points
from ((select id, name, points, 1 as which
from table1
order by rand()
limit 1
) union all
(select id, group, points, 2 as which
from table2
order by rand()
limit 1
) union all
(select id, name, points, 3 as which
from table1
order by rand()
limit 1
)
) t
order by which;

Related

How to i order values depending on its numbers of hits

I want to retrieve the table value in order of from most to least. For example, if we had a single column table like the following,
selected_val
2
3
3
2
1
3
1
1
1
4
I need a SQL that will return the values in the order of 1, 3, 2, 4, because there are four 1's, three 3's, two 2's, and one 4 in the table. I want 1,1,1,1,3,3,3,2,2,4. Is this possible?
ANd if i add more colums that
selected_val Rack
2 A
3 A
3 B
2 B
1 C
3 C
1 A
1 A
1 B
4 C
Thanks for the help
you can use count and group by
select selected_val
from my_table
group by selected_val
order by count(*) DESC
for the secondo part of the question you can use group concat if you need the rack related to selected_vale
select selected_val, group_concat(rack)
from my_table
group by selected_val
order by count(*) DESC
or add the column rack to group by if you need the relative counting and order
select selected_val, rack
from my_table
group by selected_val, rack
order by count(*) DESC
TRY THIS for the desired output and you can select other columns as well:
select t.selected_val
from test t
inner join (
select t1.selected_val, count(1) ord
from test t1
group by t1.selected_val) t2 on t2.selected_val = t.selected_val
order by t2.ord desc
OUTPUT:
1
1
1
1
3
3
3
2
2
4
Output is not actually in row but you can use GROUP_CONCAT to retrieve output in a row.
Use subquery to count, then LEFT JOIN result to the subquery's result and order by count.
select t1.selected_val from table t1
left join (
SELECT
t2.selected_val,
count(*) AS count
FROM table t2
GROUP BY selected_val
) t3 on t1.selected_val = t3.selected_val
ORDER BY t3.count DESC;
Using Cross Join.
select A.C,A.Rack from
(select selected_val,Rack,count(*) c from #TableName group by selected_val,Rack)a
,(select selected_val,Rack,count(*) c from #TableName group by selected_val,Rack)b
where B.c <= A.selected_val
ORDER BY A.selected_val DESC
OutPut :

Select two columns from two table with conditions

I want to
SELECT table1.columnA FROM table1 + ORDER BY id DESC LIMIT 1; //to get last row
and
SELECT SUM(table2.columnB) FROM table2
and then i want to do a minus condition like
SELECT table1.columnA FROM table1 ORDER BY id DESC LIMIT 1 - SELECT SUM(table2.columnB) FROM table2
but it does not work.
If what you want is the result between subtracting the sum of columnB from columnA so use this:
SELECT table1.id,table1.columnA -(select sum(columnB) from table2) as YourColumn
FROM Table1
ORDER BY table1.id desc LIMIT 1

Ensure that the correct number of rows are returned from a MySQL query

I have a (game) leaderboard table which contains a rank which is updated by another query. It is centered around the ID - when I query the table I ideally want to get back N records. So I have done a UNION on the records both with the limit N/2 like so:
(SELECT * FROM test1 t WHERE t.rank > (SELECT rank FROM test1 t2 WHERE id=ID)+0 ORDER BY rank LIMIT 0, N/2)
UNION ALL
(SELECT * FROM test1 t WHERE t.rank <= (SELECT rank FROM test1 t2 WHERE id=ID)+0 ORDER BY rank desc LIMIT 0, N/2) ORDER BY rank
Although this does not quite work when at the top of the leaderboard, it will only return the lower N/2. Is there a way to ensure that it will always return the N records? I did think that you could purposefully get more records than required and then trim the records off which you don't need. Although I do not know how to do this with a query!
Any help appreciated :)
You can do this with a clever use of order by and limit:
SELECT t.*
FROM test1 t cross join
(SELECT rank FROM test1 t2 WHERE id = #ID) as theone
ORDER BY ABS(theone.rank - t.rank)
LIMIT N;
You probably then want these back in rank order:
SELECT t.*
FROM (SELECT t.*
FROM test1 t cross join
(SELECT rank FROM test1 t2 WHERE id = #ID) as theone
ORDER BY ABS(theone.rank - t.rank)
LIMIT N
) t
ORDER BY t.rank;
Try with the following:
(SELECT * FROM test1 t WHERE t.rank > (SELECT rank FROM test1 t2 WHERE id=ID)+0 ORDER BY rank LIMIT 0,N)
UNION ALL
(SELECT * FROM test1 t WHERE t.rank <= (SELECT rank FROM test1 t2 WHERE id=ID)+0 ORDER BY rank desc LIMIT 0,N)
ORDER BY rank
LIMIT 0,N
See the manual for more insight.

How to solve this particular query?

SELECT id, count(*) as Number
FROM (SELECT id FROM t1
UNION ALL
SELECT id FROM t2
UNION ALL
SELECT id FROM t3
) t
GROUP BY id
ORDER BY Number DESC
This is the query giving me the correct result. But When I want to add where call it is throwing error.
SELECT id, count(*) as Number
FROM (SELECT id from t1
UNION ALL
select id from t2
UNION ALL
select id from t3
) t
WHERE Number > 10
GROUP BY id
ORDER BY Number DESC
You want to test conditions on an aggregate function with a HAVING clause rather than a WHERE.
select id, count(*) as Number
from (select id
from t1
UNION ALL
select id
from t2
UNION ALL
select id
from t3) t
group by id
having Number > 10
order by Number desc;
select
id,
count(*) as Number
from
(
select
id
from
t1
UNION ALL
select
id
from
t2
UNION ALL
select
id
from
t3
)t
group by
id
HAVING
Number > 10
order by
Number desc;
Try that - I think its easier to debug if you make your query easy to read...

Select the 3 most recent records where the values of one column are distinct

I have the following table:
id time text otheridentifier
-------------------------------------------
1 6 apple 4
2 7 orange 4
3 8 banana 3
4 9 pear 3
5 10 grape 2
What I want to do is select the 3 most recent records (by time desc), whose otheridentifiers are distinct. So in this case, the result would be id's: 5, 4, and 2.
id = 3 would be skipped because there's a more recent record with the same otheridentifier field.
Here's what I tried to do:
SELECT * FROM `table` GROUP BY (`otheridentifier`) ORDER BY `time` DESC LIMIT 3
However, I end up getting rows of id = 5, 3, and 1 instead of 5, 4, 2 as expected.
Can someone tell me why this query wouldn't return what I expected? I tried changing the ORDER BY to ASC but this simply rearranges the returned rows to 1, 3, 5.
It doesn't return what you expect because grouping happens before ordering, as reflected by the position of the clauses in the SQL statement. You're unfortunately going to have to get fancier to get the rows you want. Try this:
SELECT *
FROM `table`
WHERE `id` = (
SELECT `id`
FROM `table` as `alt`
WHERE `alt`.`otheridentifier` = `table`.`otheridentifier`
ORDER BY `time` DESC
LIMIT 1
)
ORDER BY `time` DESC
LIMIT 3
You could join the table on itself to filter the last entry per otheridentifier, and then take the top 3 rows of that:
SELECT last.*
FROM `table` last
LEFT JOIN `table` prev
ON prev.`otheridentifier` = last.`otheridentifier`
AND prev.`time` < last.`time`
WHERE prev.`id` is null
ORDER BY last.`time` DESC
LIMIT 3
I had a similar requirement, but I had more advanced selection criteria. Using some of the other answers I couldn't get exactly what I needed, but I found you can still do a GROUP BY after and ORDER BY like this:
SELECT t.* FROM (SELECT * FROM table ORDER BY time DESC) t
GROUP BY t.otheridentifier
SELECT * FROM table t1
WHERE t1.time =
(SELECT MAX(time) FROM table t2
WHERE t2.otheridentifier = t1.otheridentifier)
Andomar's answer is probably best in that it doesn't use a subquery.
An alternative approach:
select *
from `table` t1
where t1.`time` in (
select max(s2.`time`)
from `table` t2
group by t2.otheridentifier
)
You can use this query to get correct answer:
SELECT * FROM
(SELECT * FROM `table` order by time DESC)
t group by otheridentifier
what about
SELECT *, max(time) FROM `table` group by otheridentifier
This also:
SELECT * FROM
OrigTable T INNER JOIN
(
SELECT otheridentifier,max(time) AS duration
FROM T
GROUP BY otheridentifier) S
ON S.duration = T.time AND S.otheridentifier = T.otheridentifier.