How can I order selected rows alternatively

六月ゝ 毕业季﹏ 提交于 2019-12-23 14:24:58

问题


Here is my query:

SELECT
  pr1.id AS user_id,
  pr1.title AS user_name,
  pr2.id AS liker_id,
  pr2.title AS liker_name,
  x.which AS which_table,
  x.cnt AS total
FROM 
(
  SELECT rid, rootid, which, COUNT(*) AS cnt
  FROM
  (
    SELECT rid, rootid, 'vote' which FROM p_likes
    UNION ALL 
    SELECT rid, rootid, 'comment' which FROM p_comments
    UNION ALL 
    SELECT rid, rootid, 'friend' which FROM relations
  ) y
  WHERE y.rootid = 1246 AND y.rootid <> y.rid
  GROUP BY y.rid, y.rootid, y.which
) x
INNER JOIN pagesroot pr1 on x.rootid = pr1.id
INNER JOIN pagesroot pr2 on x.rid = pr2.id
ORDER BY x.cnt desc;

And here is the output of query above: (// means the value of that record isn't related to this question.)

+---------+-----------+----------+------------+-------------+-------+
| user_id | user_name | liker_id | liker_name | which_table | total |
+---------+-----------+----------+------------+-------------+-------+
| //      | //        | //       | //         | vote        | 7     |
| //      | //        | //       | //         | vote        | 5     |
| //      | //        | //       | //         | vote        | 3     |
| //      | //        | //       | //         | comment     | 3     |
| //      | //        | //       | //         | vote        | 2     |
| //      | //        | //       | //         | comment     | 2     |
| //      | //        | //       | //         | comment     | 2     |
| //      | //        | //       | //         | vote        | 1     |
| //      | //        | //       | //         | vote        | 1     |
| //      | //        | //       | //         | vote        | 1     |
| //      | //        | //       | //         | comment     | 1     |
| //      | //        | //       | //         | friend      | 1     |
+---------+-----------+----------+------------+-------------+-------+

All I'm trying to do is sorting rows alternatively. As you see, currently I order the results based on total column. While I need to sort them both based on total and which_table alternatively. Something like this: (expected output)

+---------+-----------+----------+------------+-------------+-------+
| user_id | user_name | liker_id | liker_name | which_table | total |
+---------+-----------+----------+------------+-------------+-------+
| //      | //        | //       | //         | vote        | 7     |
| //      | //        | //       | //         | comment     | 3     |
| //      | //        | //       | //         | friend      | 1     |
| //      | //        | //       | //         | vote        | 5     |
| //      | //        | //       | //         | comment     | 2     |
| //      | //        | //       | //         | vote        | 3     |
| //      | //        | //       | //         | comment     | 2     |
| //      | //        | //       | //         | vote        | 2     |
| //      | //        | //       | //         | comment     | 1     |
| //      | //        | //       | //         | vote        | 1     |
| //      | //        | //       | //         | vote        | 1     |
| //      | //        | //       | //         | vote        | 1     |
+---------+-----------+----------+------------+-------------+-------+

How can I do that?


回答1:


Please try this below query. Using ROW_NUMBER() OVER(PARTITION BY ..) generate a rank/record number for each 'which' items and sort based on this . (Hope this will work for you, i don't have the table schema or sample data script to try myself)

SELECT
  pr1.id AS user_id,
  pr1.title AS user_name,
  pr2.id AS liker_id,
  pr2.title AS liker_name,
  x.which AS which_table,
  x.cnt AS total
FROM 
(
  SELECT rid, rootid, which, COUNT(*) AS cnt
        ,ROW_NUMBER() OVER(PARTITION  BY which ORDER BY rid) AS new_order
  FROM
  (
    SELECT rid, rootid, 'vote' which FROM p_likes
    UNION ALL 
    SELECT rid, rootid, 'comment' which FROM p_comments
    UNION ALL 
    SELECT rid, rootid, 'friend' which FROM relations
  ) y
  WHERE y.rootid = 1246 AND y.rootid <> y.rid
  GROUP BY y.rid, y.rootid, y.which
) x
INNER JOIN pagesroot pr1 on x.rootid = pr1.id
INNER JOIN pagesroot pr2 on x.rid = pr2.id
ORDER BY new_order,x.cnt desc;



回答2:


I don't think this is all that difficult - my model below doesn't differ in principal from the question and I use correlated sub queries to allocate the vote (in my model live) total for all whichs for an id

MariaDB [sandbox]> select * from onetime_contest;
+------+-----------+------------+
| id   | status    | valid_till |
+------+-----------+------------+
|    1 | live      | 2017-01-01 |
|    2 | waiting   | 2017-01-01 |
|    3 | completed | 2017-01-01 |
|    4 | Waiting   | 2017-01-01 |
|    5 | live      | 2017-06-01 |
|    6 | waiting   | 2017-06-01 |
|    7 | completed | 2017-06-01 |
|    8 | Waiting   | 2017-06-01 |
|    1 | Live      | 2017-01-01 |
|    2 | Live      | 2017-01-01 |
|    3 | Live      | 2017-01-01 |
|    3 | Waitng    | 2017-01-01 |
|    4 | Live      | 2017-01-01 |
|    6 | Live      | 2017-01-01 |
|    7 | Live      | 2017-01-01 |
|    8 | Live      | 2017-01-01 |
|    1 | Waiting   | 2017-01-01 |
|    2 | Waiting   | 2017-01-01 |
|    2 | Live      | 2017-01-01 |
|    2 | Waiting   | 2017-01-01 |
|    2 | Live      | 2017-01-01 |
|    2 | Live      | 2017-01-01 |
+------+-----------+------------+
22 rows in set (0.00 sec)

MariaDB [sandbox]>
MariaDB [sandbox]>
MariaDB [sandbox]> select * from
    -> (
    -> select id, status ,count(*) as t1 ,count(*) as t2 from onetime_contest o1 where status = 'Live' group by id,status
    -> union
    -> select id, status ,count(*) as t1 ,(select count(*) from onetime_contest o2 where status = 'Live' and o2.id = o1.id  group by o2.id,o2.status)
    ->   from onetime_contest o1 where status = 'Waiting' group by id,status
    -> union
    -> select id, status ,count(*) as t1 ,(select count(*) from onetime_contest o2 where status = 'Live' and o2.id = o1.id  group by o2.id,o2.status)
    ->  from onetime_contest o1 where status = 'Completed' group by id,status
    -> ) s
    -> order by s.t2 desc,s.id,
    -> case when s.status = 'Live' then 1
    ->  when s.status = 'Waiting' then 2
    -> else 3 end;
+------+-----------+----+------+
| id   | status    | t1 | t2   |
+------+-----------+----+------+
|    2 | Live      |  4 |    4 |
|    2 | waiting   |  3 |    4 |
|    1 | live      |  2 |    2 |
|    1 | Waiting   |  1 |    2 |
|    3 | Live      |  1 |    1 |
|    3 | completed |  1 |    1 |
|    4 | Live      |  1 |    1 |
|    4 | Waiting   |  1 |    1 |
|    5 | live      |  1 |    1 |
|    6 | Live      |  1 |    1 |
|    6 | waiting   |  1 |    1 |
|    7 | Live      |  1 |    1 |
|    7 | completed |  1 |    1 |
|    8 | Live      |  1 |    1 |
|    8 | Waiting   |  1 |    1 |
+------+-----------+----+------+
15 rows in set (0.00 sec)



回答3:


If I understand well your question, you can use:

SELECT SELECT pr1.id AS user_id, pr1.title AS user_name, pr2.id AS liker_id, pr2.title AS liker_name, x.which AS which_table, x.cnt AS total, FROM ( SELECT rid, rootid, which, COUNT(*) AS cnt FROM ( SELECT rid, rootid, 'vote' which FROM p_likes UNION ALL SELECT rid, rootid, 'comment' which FROM p_comments UNION ALL SELECT rid, rootid, 'friend' which FROM relations ) y WHERE y.rootid = 1246 AND y.rootid <> y.rid GROUP BY y.rid, y.rootid, y.which ) x INNER JOIN pagesroot pr1 on x.rootid = pr1.id INNER JOIN pagesroot pr2 on x.rid = pr2.id ORDER BY 1,2,3,4,5,6;

These numbers represent your columns. So, if you want to sort them based on total and which_table, you can write: SELECT(your code) order by 5,6



来源:https://stackoverflow.com/questions/41974970/how-can-i-order-selected-rows-alternatively

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!