Mysql4:用于选择一条或零条记录的SQL

时间:2009-02-27 20:48:28

标签: sql mysql database

表格布局:

CREATE TABLE t_order  (id INT, custId INT, order DATE)

我正在寻找一个SQL命令来为每个订单选择最多一行(拥有该订单的客户由名为custId的字段标识)。

如果没有为任何行指定订单日期,我想选择客户订单的 ONE (无论哪一个,按ID排序)。

如果已存在具有给定订单日期的记录,我想检索customerId的空Resultset。

这是一个例子。每个客户最多应该有一个订单(一个没有给出日期)。已经存在日期值的订单根本不应出现。

  +---------------------------------------------------------+
  |id    |    custId       |  date                          |
  +---------------------------------------------------------+
  | 1              10         NULL                          |
  | 2              11         2008-11-11                    |
  | 3              12         2008-10-23                    |
  | 4              11         NULL                          |
  | 5              13         NULL                          |
  | 6              13         NULL                          |
  +---------------------------------------------------------+
                           |
                           |
                           |      Result
                         \ |  /
                          \  /
  +---------------------------------------------------------+
  |id    |    custId       |  date                          |
  +---------------------------------------------------------+
  | 1              10         NULL                          |
  |                                                         |
  |                                                         |
  |                                                         |
  | 5              13         NULL                          |
  |                                                         |
  +---------------------------------------------------------+
                                powered be JavE

编辑: 我选择格拉维奇的答案是正确的,因为它提供了 稍微修改数据的正确结果:

  +---------------------------------------------------------+
  |id    |    custId       |  date                          |
  +---------------------------------------------------------+
  | 1              10         NULL                          |
  | 2              11         2008-11-11                    |
  | 3              12         2008-10-23                    |
  | 4              11         NULL                          |
  | 5              13         NULL                          |
  | 6              13         NULL                          |
  | 7              11         NULL                          |
  +---------------------------------------------------------+

当客户出现两次以上因为其where子句约束a.id!= b.id时,Sfossen的答案将不起作用。

Quassnoi的答案对我不起作用,因为我运行服务器版本4.0.24,产生以下错误: alt text http://img25.imageshack.us/img25/8186/picture1vyj.png

4 个答案:

答案 0 :(得分:2)

对于特定客户,它是:

SELECT *
FROM t_order
WHERE date IS NULL AND custId=? LIMIT 1

对于所有客户:

SELECT a.*
FROM t_order a 
    LEFT JOIN t_order b ON a.custId=b.custID and a.id != b.id
WHERE a.date IS NULL AND b.date IS NULL
GROUP BY custId;

答案 1 :(得分:1)

试试这个:

SELECT to1.*
FROM t_order AS to1
WHERE
    to1.date IS NULL AND 
    to1.custId NOT IN (
        SELECT to2.custId
        FROM t_order AS to2
        WHERE to2.date IS NOT NULL
        GROUP BY to2.custId
    )
GROUP BY to1.custId

对于MySQL 4:

SELECT to1.*
FROM t_order AS to1
LEFT JOIN t_order AS to2 ON
    to2.custId = to1.custId AND
    to2.date IS NOT NULL
WHERE
    to1.date IS NULL AND 
    to2.id IS NULL
GROUP BY to1.custId

答案 2 :(得分:1)

此查询将在custId上使用一次传递索引。

对于每个不同的custId,它将在相同的索引上使用一个子查询。

如果你的牌桌很大,

没有GROUP BY,没有TEMPORARY和没有FILESORT - 效率很高。

SELECT VERSION()

--------
'4.1.22-standard'

CREATE INDEX ix_order_cust_id ON t_order(custId)

SELECT id, custId, order_date
FROM (
  SELECT o.*,
    CASE
      WHEN custId <> @c THEN
        (
        SELECT 1
        FROM   t_order oi
        WHERE  oi.custId = o.custId
          AND  order_date IS NOT NULL
        LIMIT 1
        )
    END AS n,
    @c <> custId AS f,
    @c := custId
  FROM
    (
    SELECT @c := -1
    ) r,
    t_order o
  ORDER BY custId
) oo
WHERE n IS NULL AND f

---------
1, 10, ''
5, 13, ''

答案 3 :(得分:0)

首先过滤掉带有日期的行,然后过滤掉具有较低ID的类似行的任何行。这应该有效,因为如果id是唯一的,具有最小id的匹配记录是唯一的。

select * from t_order o1
    where date is null
      and not exists (select * from t_order o2
                         where o2.date is null
                           and o1.custId = o2.custId
                           and o1.id > o2.id)