MySQL

MySQLのUNIONの便利な使い道

More than 1 year has passed since last update.
CREATE TABLE news (
    title VARCHAR(255),
    category VARCHAR(50),
    date DATE
);
INSERT INTO news 
VALUES 
    ('政治ニュース1', 'seiji', '2012-01-21'),
    ('政治ニュース2', 'seiji', '2012-01-22'),
    ('政治ニュース3', 'seiji', '2012-01-23'),
    ('経済ニュース1', 'keizai', '2012-01-21'),
    ('経済ニュース2', 'keizai', '2012-01-22'),
    ('経済ニュース3', 'keizai', '2012-01-23'),
    ('エンタメニュース1', 'entame', '2012-01-21'),
    ('エンタメニュース2', 'entame', '2012-01-22'),
    ('エンタメニュース3', 'entame', '2012-01-23'),
    ('コラム1', 'koramu', '2012-01-23'),
    ('コラム2', 'koramu', '2012-01-24');

上記のデータに対して「最新ニュースを5件表示したい」という要望があったとする。
その場合、単純に次のクエリになる。

mysql> SELECT * FROM news ORDER BY date DESC LIMIT 5;
+---------------------------+----------+------------+
| title                     | category | date       |
+---------------------------+----------+------------+
| コラム2                   | koramu   | 2012-01-24 |
| コラム1                   | koramu   | 2012-01-23 |
| エンタメニュース3         | entame   | 2012-01-23 |
| 経済ニュース3             | keizai   | 2012-01-23 |
| 政治ニュース3             | seiji    | 2012-01-23 |
+---------------------------+----------+------------+

さらに、追加要件として「コラムは最新1件を必ず表示する」があったとする。
そして、いやらしくも「時系列順に表示されること」という内容。

この処理をやろうとすると、PHPで別々のクエリを発行してあとでマージ&ソート、
なんていうことになりそうだけど、UNIONを使うと簡単に取れる。

mysql> (SELECT * FROM news WHERE category != 'koramu' ORDER BY date DESC LIMIT 4)
    -> UNION
    -> (SELECT * FROM news WHERE category = 'koramu' ORDER BY date DESC LIMIT 1)
    -> ORDER BY date DESC;
+---------------------------+----------+------------+
| title                     | category | date       |
+---------------------------+----------+------------+
| コラム2                   | koramu   | 2012-01-24 |
| 政治ニュース3             | seiji    | 2012-01-23 |
| エンタメニュース3         | entame   | 2012-01-23 |
| 経済ニュース3             | keizai   | 2012-01-23 |
| 経済ニュース2             | keizai   | 2012-01-22 |
+---------------------------+----------+------------+