简体   繁体   中英

Division in SQL Query Statement

I have two queries that return a single column of double precision values:

(SELECT scale 
   FROM (SELECT title, 
                scale,
                dense_rank() OVER (PARTITION BY title 
                                       ORDER BY scale ASC) AS r 
           FROM signatures) t
  WHERE r = 1)

...and:

(SELECT scale 
   FROM (SELECT scale,
                dense_rank() OVER (PARTITION BY title 
                                       ORDER BY scale ASC) AS r 
           FROM signatures) t
  WHERE r = 2) 

I am trying to SELECT the first query (Q1) divided by the second query (Q2). Ie, (Row1 from Q1) / (Row1 from Q2). And continued down the rest of the rows.

I have tried:

SELECT ((SELECT scale 
           FROM (SELECT title, 
                        scale,
                        dense_rank() OVER (PARTITION BY title  
                                               ORDER BY scale ASC) AS r 
                   FROM signatures) t
          WHERE r = 1)

/

(SELECT scale 
   FROM (SELECT scale,
                dense_rank() OVER (PARTITION BY title 
                                       ORDER BY scale ASC) AS r 
           FROM signatures) t
  WHERE r = 2) 
)

But have had no luck. Can anyone see a way to do this? I can send the two queries separately, then run through a loop and divide the elements, but that won't work for a semi-large recordset.

Also, it shouldn't matter, but I am using PostgreSQL.

I think you want to use the LEAD window function rather than getting two sets and trying to join them. This allows you to make a reference to another row in the same window (ie with a matching partition by ). Something like:

select title, scale / next_scale
from ( select title, scale,
              lead(scale) over(partition by title order by scale asc) as next_scale,
              row_number() over(partition by title order by scale asc) as agg_row
       from signatures
     ) agg
where agg_row = 1;

Here, lead(scale) takes the value from the scale column from the next row to be output in the same window, ie the next-most scale in order. We still need to project row_number() and filter on it so that we just get output rows for the first row in each window, ie the row with the least scale for each title.

You need to give SQL some way of knowing which figure in each column to divide by which. Try this:

    SELECT first.title, (first.scale / second.scale) ratio
      FROM 
           (SELECT scale, title
              FROM (SELECT title, scale,
                           dense_rank() OVER 
                             (PARTITION BY title ORDER BY scale ASC) AS r
                      FROM signatures) t
             WHERE r = 1) first
INNER JOIN
           (SELECT scale, title
              FROM (SELECT title, scale,
                           dense_rank() OVER
                             (PARTITION BY title ORDER BY scale ASC) AS r
                      FROM signatures) t
             WHERE r = 2) second
        ON first.title = second.title

As OMG commented, DENSE_RANK may give you trouble if you end up with several identical scale values. You may wish to limit each subquery to one row per title if that is appropriate for your logic, or alternatively specify SELECT DISTINCT in the outer query as the duplicates will be exact duplicates.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM