2013-02-07 50 views
0

说选择列我有两个表:从一个表或其他

CREATE TABLE state (
    id TINYINT, 
    state CHAR(2), 
    PRIMARY KEY (id) 
); 

CREATE TABLE valid_state (
    id INT, 
    state CHAR(2), # or stateId TINYINT or whatever 
    productId INT 
); 

如果一个产品只能在CA出售它会在valid_state一个条目。如果它可以在所有州销售,则不会在valid_state中有任何条目。如果无法在任何状态下销售,则需要在未定义产品表中禁用该产品。

我的问题是:我如何选择给定产品的所有有效状态?理想情况下,我想从valid_state中选择,查看它是否为空,如果是,则返回所有状态。不幸的是,我不知道该怎么做。

任何想法?

(还,FWIW,我没有设计架构,以便建议我改变它是不是有帮助),你可以做到这一点

回答

1

一种方式是使用和UNIONNOT EXISTS

SELECT DISTINCT S.Id, 
    S.State 
FROM State S 
    JOIN valid_state V ON S.State = V.State AND V.ProductId = @ProductId 
UNION 
SELECT DISTINCT S.Id, 
    S.State 
FROM State S 
WHERE NOT EXISTS (SELECT * FROM valid_state WHERE ProductId = @ProductId) 

以下是样本Fiddle

祝你好运。

0

我想出了一个不同的方法。

我得到所有的状态,并标记哪些是有效的第一个左加入给定的产品。

随着第二次加入我采取了所有的产品是有效的并加入在一起的状态。没有V.id = V2.id我会有valid_states * 2行返回,但与它,我只是我想要的。

SELECT S.Id, S.State 
FROM state S 
LEFT JOIN valid_state V 
    ON V.state = S.state 
    AND productId = @ProductId 
LEFT JOIN (state S2, valid_state V2) 
    ON V2.productId = @ProductId 
     AND S2.state = S.state 
WHERE V.id = V2.id OR V2.id IS NULL; 

我不知道哪一个更好。 sgeddes的EXPLAIN显示它正在查看3 * 3 * 3行,而我的是3 * 3 * 3 * 3。但sgeddes已在EXPLAIN五列(其中两个为NULL值的行),是“使用临时”,“使用连接缓冲”,有一个“不可能WHERE”

任何想法?