2009-02-27 91 views
1

表佈局:Mysql4:SQL選擇一個或零記錄

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

我正在尋找一個SQL命令來選擇每個訂單最多隻能有一個排的(誰擁有了訂單的客戶通過鑑定字段命名爲custId)。

我想選擇ONE如果沒有爲任何行給出的訂單日期,那麼客戶的訂單(無論哪一個,按照ID排序都無關緊要)。

我想檢索客戶ID的空結果,如果存在與給定的順序日期的記錄。

下面是一個例子。每個客戶最多隻能有一個訂單(一個沒有給定日期)。已經有日期值的訂單不應該出現。

 
    +---------------------------------------------------------+ 
    |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 

編輯: 我選擇glavić的答案正確的,因爲它提供 正確的結果略有修改數據:

 
    +---------------------------------------------------------+ 
    |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       | 
    +---------------------------------------------------------+ 

Sfossen的答案,當客戶出現以上將無法正常工作兩次因爲where子句約束a.id!= b.id.

Quassnoi的答案不適合我的工作,因爲我跑的服務器版本4.0.24這將產生以下錯誤: alt text http://img25.imageshack.us/img25/8186/picture1vyj.png

+0

此表中還有其他哪些列?帶有空日期的custID沒有理由存在? – awithrow 2009-02-27 21:24:12

+0

您是否測試過任何答案以查看它是否適合您? – sfossen 2009-02-27 22:51:06

+0

我測試過了。在給定的數據全部三項工作:@ sfossen的,@ glavic的和我的。 – Quassnoi 2009-02-27 22:53:00

回答

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

對於特定客戶它是:

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

這個查詢將使用一個傳過來指數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, '' 
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)