简体   繁体   中英

Mysql multiple ORDER BY with UNION

I want to get data with order by date. I am using union.

I have gone through the below url. But I am not getting clear solution with that.

mysql order by with union doesn't seem to work

My Query

(SELECT n.nid, 
        Max(na.gid)                 AS mid, 
        fav.field_date_posted_value AS pdate 
 FROM   `node` AS n 
 JOIN nodeaccess AS na 
   ON na.nid = n.nid 
 LEFT JOIN field_data_field_date_posted AS fav 
        ON fav.entity_id = n.nid 
 WHERE  ( na.gid IN( 10, 11 ) 
          AND ( n.status = '1' ) 
          AND ( n.type IN ( 'article', 'blog', 'events', 'media', 
                            'press_releases', 'expert_speak', 'feature', 
                            'case_study', 
                            'news', 'the_igtb_series', 'trend', 'white_paper' ) 
              ) ) 
 GROUP  BY n.nid 
 ORDER  BY pdate DESC) 

UNION 

(SELECT n.nid, 
        Max(na.gid)                 AS mid, 
        fav.field_date_posted_value AS pdate 
 FROM   `node` AS n 
 JOIN nodeaccess AS na 
   ON na.nid = n.nid 
 LEFT JOIN field_data_field_date_posted AS fav 
        ON fav.entity_id = n.nid 
 WHERE  ( na.gid IN( 2 ) 
          AND ( n.status = '1' ) 
          AND ( n.type IN ( 'article', 'blog', 'events', 'media', 
                            'press_releases', 'expert_speak', 'feature', 
                            'case_study', 
                            'news', 'the_igtb_series', 'trend', 'white_paper' ) 
              ) ) 
 GROUP  BY n.nid 
 ORDER  BY pdate DESC) 
LIMIT 
10 

My Result

+-------+------+---------------------+
| nid   | mid  | pdate               |
+-------+------+---------------------+
| 12472 |   10 | 2015-05-11 00:00:00 |
| 12473 |   10 | 2015-04-03 00:00:00 |
| 12475 |   10 | 2015-06-08 00:00:00 |
| 12476 |   10 | 2015-12-15 01:55:48 |
| 12477 |   10 | 2014-06-30 00:00:00 |
| 12478 |   10 | 2013-12-26 00:00:00 |
| 12482 |   10 | 2014-02-02 00:00:00 |
| 12483 |   10 | 2014-09-01 00:00:00 |
| 12484 |   10 | 2015-12-04 00:00:00 |
| 12485 |   10 | 2015-08-14 00:00:00 |
+-------+------+---------------------+

In the above url the date order is not working. I don't want to make order by as common. I need separate order by for both select queries (Used in UNION).

Update 2:

(SELECT n.nid, max(na.gid) as mid, fav.field_date_posted_value as pdate FROM `node` as n
JOIN nodeaccess AS na ON na.nid = n.nid
LEFT JOIN field_data_field_date_posted AS fav ON fav.entity_id = n.nid
WHERE (na.gid IN(10,11) AND (n.status = '1') AND (n.type IN  ('article','blog', 'events', 'media', 'press_releases', 'expert_speak', 'feature', 'case_study', 'news', 'the_igtb_series', 'trend', 'white_paper')) )
GROUP BY n.nid 
ORDER BY pdate DESC)

UNION

(SELECT n.nid, max(na.gid) as mid, fav.field_date_posted_value as pdate FROM `node` as n
JOIN nodeaccess AS na ON na.nid = n.nid
LEFT JOIN field_data_field_date_posted AS fav ON fav.entity_id = n.nid
WHERE (na.gid IN(2) AND (n.status = '1') AND (n.type IN  ('article','blog', 'events', 'media', 'press_releases', 'expert_speak', 'feature', 'case_study', 'news', 'the_igtb_series', 'trend', 'white_paper')) )
GROUP BY n.nid 
ORDER BY pdate DESC)

ORDER BY pdate DESC LIMIT 10

The above gives the below result.

+-------+------+---------------------+
| nid   | mid  | pdate               |
+-------+------+---------------------+
| 12789 |   11 | 2016-09-26 00:00:00 |
| 12826 |    2 | 2016-07-13 00:00:00 |
| 12845 |    2 | 2016-07-05 00:00:00 |
| 12823 |   10 | 2016-06-21 00:00:00 |
| 12822 |    2 | 2016-06-17 00:00:00 |
| 12821 |   10 | 2016-06-07 00:00:00 |
| 12635 |   10 | 2016-06-07 00:00:00 |
| 12821 |    2 | 2016-06-07 00:00:00 |
| 12633 |   10 | 2016-05-25 02:19:29 |
| 12548 |   10 | 2016-05-20 00:00:00 |
+-------+------+---------------------+

In this result I don't want to reorder the column " mid "

You need to wrap the outcome of union of both select statements and order it by pdate .

as below:

SELECT * from 
    (
        (SELECT n.nid, max(na.gid) as mid, fav.field_date_posted_value as pdate FROM `node` as n
        JOIN nodeaccess AS na ON na.nid = n.nid
        LEFT JOIN field_data_field_date_posted AS fav ON fav.entity_id = n.nid
        WHERE (na.gid IN(10,11) AND (n.status = '1') AND (n.type IN  ('article','blog', 'events', 'media', 'press_releases', 'expert_speak', 'feature', 'case_study', 'news', 'the_igtb_series', 'trend', 'white_paper')) )
        GROUP BY n.nid 
        ORDER BY pdate DESC)

        UNION

        (SELECT n.nid, max(na.gid) as mid, fav.field_date_posted_value as pdate FROM `node` as n
        JOIN nodeaccess AS na ON na.nid = n.nid
        LEFT JOIN field_data_field_date_posted AS fav ON fav.entity_id = n.nid
        WHERE (na.gid IN(2) AND (n.status = '1') AND (n.type IN  ('article','blog', 'events', 'media', 'press_releases', 'expert_speak', 'feature', 'case_study', 'news', 'the_igtb_series', 'trend', 'white_paper')) )
        GROUP BY n.nid 
        ORDER BY pdate DESC)
    ) as UnionTable 
ORDER BY pdate DESC limit 10

I'm not sure why a union is even needed. And, I don't fully understand what the third column value is supposed to be, because it is not the argument to an aggregation function and is not in the group by .

However, I would write the query as:

(SELECT n.nid, max(na.gid) as mid, fav.field_date_posted_value as pdate
 FROM `node` n JOIN
      nodeaccess na
      ON na.nid = n.nid LEFT JOIN
      field_data_field_date_posted fav
      ON fav.entity_id = n.nid
 WHERE (na.gid IN(10,11) AND (n.status = '1') AND (n.type IN  ('article','blog', 'events', 'media', 'press_releases', 'expert_speak', 'feature', 'case_study', 'news', 'the_igtb_series', 'trend', 'white_paper')) )
 GROUP BY n.nid 
 ORDER BY pdate DESC
 LIMIT 10
) UNION ALL
(SELECT n.nid, max(na.gid) as mid, fav.field_date_posted_value as pdate
FROM `node` n JOIN
     nodeaccess na
     ON na.nid = n.nid LEFT JOIN
     field_data_field_date_posted fav
     ON fav.entity_id = n.nid
 WHERE (na.gid IN(2) AND (n.status = '1') AND (n.type IN  ('article','blog', 'events', 'media', 'press_releases', 'expert_speak', 'feature', 'case_study', 'news', 'the_igtb_series', 'trend', 'white_paper')) )
 GROUP BY n.nid 
 ORDER BY pdate DESC
 LIMIT 10
)
ORDER BY pdate DESC
LIMIT 10;

Notes:

  • Limit the subqueries to 10 rows. Why bother processing more data than needed?
  • Use an ORDER BY after the subqueries to order all the results.
  • Use UNION ALL instead of UNION so your query does not incur the overhead of removing duplicates.

Create one additional column so you can order each UNION query

Sql Fiddle Demo

SELECT '1' as grp, 1 as ID
UNION 
SELECT '1' as grp, 3 as ID
UNION
SELECT '1' as grp, 2 as ID
UNION
SELECT '1' as grp, 5 as ID
UNION 
SELECT '2' as grp, 4 as ID
UNION 
SELECT '2' as grp, 7 as ID
UNION
SELECT '2' as grp, 2 as ID
UNION
SELECT '2' as grp, 5 as ID

ORDER BY grp, ID

OUTPUT

在此处输入图片说明

Two additional ORDER BY Clause can be removed. In fact few DB only to put ORDER BY OR LIMIT clause before Union statement. You might want to try below:

    (
(SELECT n.nid, max(na.gid) as mid, fav.field_date_posted_value as pdate FROM `node` as n
JOIN nodeaccess AS na ON na.nid = n.nid
LEFT JOIN field_data_field_date_posted AS fav ON fav.entity_id = n.nid
WHERE (na.gid IN(10,11) AND (n.status = '1') AND (n.type IN  ('article','blog', 'events', 'media', 'press_releases', 'expert_speak', 'feature', 'case_study', 'news', 'the_igtb_series', 'trend', 'white_paper')) )
GROUP BY n.nid 
 )

UNION

(SELECT n.nid, max(na.gid) as mid, fav.field_date_posted_value as pdate FROM `node` as n
JOIN nodeaccess AS na ON na.nid = n.nid
LEFT JOIN field_data_field_date_posted AS fav ON fav.entity_id = n.nid
WHERE (na.gid IN(2) AND (n.status = '1') AND (n.type IN  ('article','blog', 'events', 'media', 'press_releases', 'expert_speak', 'feature', 'case_study', 'news', 'the_igtb_series', 'trend', 'white_paper')) )
GROUP BY n.nid) 
) order by pdate DESC limit 10

Try this

SELECT n.nid, max(na.gid) as mid,fav.field_date_posted_value, UNIX_TIMESTAMP(fav.field_date_posted_value) as pdate, 1 as ob FROM `node` as n
JOIN nodeaccess AS na ON na.nid = n.nid
LEFT JOIN field_data_field_date_posted AS fav ON fav.entity_id = n.nid
WHERE (na.gid IN(10,11) AND (n.status = '1') AND (n.type IN  ('article','blog', 'events', 'media', 'press_releases', 'expert_speak', 'feature', 'case_study', 'news', 'the_igtb_series', 'trend', 'white_paper')) )
GROUP BY n.nid 


UNION ALL

SELECT n.nid, max(na.gid) as mid,fav.field_date_posted_value, UNIX_TIMESTAMP(fav.field_date_posted_value) as pdate, 2 as ob FROM `node` as n
JOIN nodeaccess AS na ON na.nid = n.nid
LEFT JOIN field_data_field_date_posted AS fav ON fav.entity_id = n.nid
WHERE (na.gid IN(2) AND (n.status = '1') AND (n.type IN  ('article','blog', 'events', 'media', 'press_releases', 'expert_speak', 'feature', 'case_study', 'news', 'the_igtb_series', 'trend', 'white_paper')) )
GROUP BY n.nid  

ORDER BY ob ASC, pdate DESC

Fixed the order by date only base or group

I use temporary tables to resolve ordering issues on union:

CREATE TEMPORARY TABLE IF NOT EXISTS temp_table1 AS 
(  
SELECT *   
FROM  table1   
ORDER BY < your specific order > )  

CREATE TEMPORARY TABLE IF NOT EXISTS temp_table2 AS 
(  
SELECT *   
FROM table2    
ORDER BY < your specific order > )  

SELECT * FROM temp_table1   
UNION ALL  
SELECT * FROM temp_table2   

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