选择指定年份的新项目或返回项目

时间:2014-09-15 17:52:03

标签: mysql sql union self-join

我有一张看起来像这样的表:

+---------------------+----------+
| date                | item     |
+---------------------+----------+
| 2008-11-30 11:15:59 | Plums    |
| 2012-11-08 19:42:37 | Lemons   |
| 2013-01-30 18:58:07 | Apples   |
| 2013-02-12 13:44:45 | Pears    |
| 2014-06-08 11:46:48 | Apples   |
| 2014-09-01 20:28:03 | Oranges  |
+---------------------+----------+

我现在想为两种情况选择项目:

1)我想选择今年(或不同的指定年份)的所有不同项目,这些项目今年是新的,这意味着它们在前几年没有出现过。因此,此查询应该给我" Oranges"因此,2014年。

2)我还想为这个(或另一个指定的)年份选择所有不同的项目,这些项目是返回,这显然意味着它们已经出现在前几年。这个查询应该给我" Apples"因此,2014年。

为了澄清,我想将这两个查询仅用于与前几年的比较。因此,如果我将2013指定为运行此查询的年份," Apples"应该显示为新的,而不是返回。

我不一定在一个查询中需要这两件事(我怀疑它是否可能),所以两个不同的查询,每个案例一个,完全没问题。

3 个答案:

答案 0 :(得分:2)

项目(<{3}})如何:

SELECT DISTINCT m1.item
FROM MyTable m1
  LEFT JOIN MyTable m2 ON m1.item = m2.item AND YEAR(m2.date) < 2014
WHERE YEAR(m1.date) = 2014
  AND m2.date IS NULL

和(SQL Fiddle退回项:

SELECT DISTINCT m1.item
FROM MyTable m1
  INNER JOIN MyTable m2 ON m1.item = m2.item
WHERE YEAR(m1.date) = 2014
  AND YEAR(m2.date) < 2014

如果您想将两个查询合并在一起(SQL FiddleSQL Fiddle):

SELECT DISTINCT m1.item, 'New' AS Status
FROM MyTable m1
  LEFT JOIN MyTable m2 ON m1.item = m2.item AND YEAR(m2.date) < 2014
WHERE YEAR(m1.date) = 2014
  AND m2.date IS NULL
UNION ALL
SELECT DISTINCT m1.item, 'Returning' AS Status
FROM MyTable m1
  INNER JOIN MyTable m2 ON m1.item = m2.item
WHERE YEAR(m1.date) = 2014
  AND YEAR(m2.date) < 2014
ORDER BY Status;

答案 1 :(得分:2)

1 - 此解决方案可以使用索引

SELECT DISTINCT x.item 
  FROM my_table x 
  LEFT 
  JOIN my_table y 
    ON y.item = x.item 
   AND y.date < x.date 
 WHERE x.date BETWEEN '2014-01-01' AND '2014-12-31' AND y.date IS NULL;

2 - 这也可以......

SELECT DISTINCT x.item 
  FROM my_table x 
  JOIN my_table y 
    ON y.item = x.item 
   AND y.date < x.date 
 WHERE x.date BETWEEN '2014-01-01' AND '2014-12-31';

2显然是一个比1更简单的问题,所以我对你按此顺序要求它们感到有些惊讶!?!?

如果你从第一个查询中删除了WHERE ... IS NULL,那么你实际上得到了你“怀疑可能”的答案,但是这两个查询的UNION将达到同样的效果。

答案 2 :(得分:1)

这将为您提供特定年份的水果,而不是其他年份的水果

SELECT t.item 
FROM table t 
WHERE YEAR(t.date) = 2014 
  AND NOT EXISTS (SELECT 1 FROM table f WHERE YEAR(f.date) <> 2014 AND f.item = t.item)

这将为您提供超过一年的

SELECT t.item 
FROM table t 
WHERE YEAR(t.date) = 2014 
  AND EXISTS (SELECT 1 FROM table f WHERE YEAR(f.date) <> 2014 AND f.item = t.item)

你可以把它们全部放在一起。

SELECT t.item as "NEW", f.item as 'RETURNING'
FROM
(   SELECT t.item, @a := (COALESCE(@a, 0) + 1) as join_col 
    FROM test t 
    WHERE YEAR(t.date) = 2014 
      AND NOT EXISTS (SELECT 1 FROM test f WHERE YEAR(f.date) <> 2014 AND f.item = t.item)
) t
LEFT JOIN
(   SELECT t.item , @b := (COALESCE(@b, 0) + 1) as join_col 
    FROM test t 
    WHERE YEAR(t.date) = 2014 
      AND EXISTS (SELECT 1 FROM test f WHERE YEAR(f.date) <> 2014 AND f.item = t.item)
) f ON f.join_col = t.join_col;

DEMO