How to get this SQL query to output two rows, not two fields?

Here is my SQL query, it creates a single resulting row with two columns "below" and "above". They correspond to the primary keys ("id") of the rows in the Rankable table.

The purpose of the query is to select a random pair of Rankable rows that is not yet in the comparison table (which contains all the previous pairs).

However, I need this query to return two Rankables as strings, not just Rankable identifiers as fields on the same row.

This is the current request:

SELECT a.id AS lower, b.id AS higher
FROM Rankable a
INNER JOIN Rankable b on a.id < b.id
WHERE 
  a.category_id = ? AND b.category_id = ?
  AND NOT EXISTS (
    SELECT *
    FROM Comparison c
    WHERE c.lower_id in (a.id, b.id))
  AND NOT EXISTS (
    SELECT *
    FROM Comparison c
    WHERE c.higher_id IN (a.id, b.id))
ORDER BY a.id * rand()
LIMIT 1;
+1
source share
3 answers

I call it hacking MySQL ..

select @a as one
from
(

    SELECT @a := a.id, @b := b.id
    FROM Rankable a
    INNER JOIN Rankable b on a.id < b.id
    WHERE 
      a.category_id = ? AND b.category_id = ?
      AND NOT EXISTS (
        SELECT *
        FROM Comparison c
        WHERE c.lower_id in (a.id, b.id))
      AND NOT EXISTS (
        SELECT *
        FROM Comparison c
        WHERE c.higher_id IN (a.id, b.id))
    ORDER BY a.id * rand()
    LIMIT 1
) SQ
union all
select @b

To join the table to get all the other columns:

select Rankable.*
from
(
    select 1 as Sort, @a as one
    from
    (

        SELECT @a := a.id, @b := b.id
        FROM Rankable a
        INNER JOIN Rankable b on a.id < b.id
        WHERE 
          a.category_id = ? AND b.category_id = ?
          AND NOT EXISTS (
            SELECT *
            FROM Comparison c
            WHERE c.lower_id in (a.id, b.id))
          AND NOT EXISTS (
            SELECT *
            FROM Comparison c
            WHERE c.higher_id IN (a.id, b.id))
        ORDER BY a.id * rand()
        LIMIT 1
    ) SQ
    union all
    select 2, @b
) X
INNER JOIN Rankable ON Rankable.Id = X.one
ORDER BY X.Sort
+2
source

2 , . , , . "" "

0

Not really, but I think this will work:

SELECT * FROM Rankable JOIN (
  SELECT a.id AS lower, b.id AS higher 
  FROM Rankable a 
  INNER JOIN Rankable b on a.id < b.id 
  WHERE    
    a.category_id = ? AND b.category_id = ?   
    AND NOT EXISTS (
      SELECT *
      FROM Comparison c
      WHERE c.lower_id in (a.id, b.id)
      )
    AND NOT EXISTS (
      SELECT *
      FROM Comparison c
      WHERE c.higher_id IN (a.id, b.id)
      )
   ORDER BY a.id * rand() 
   ) AS rank_them
ON (Rankable.id = rank_them.higher OR Rankable.id = rank_them.lower)
0
source

Source: https://habr.com/ru/post/1788357/


All Articles