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,我没有设计架构,所以建议我改变它并没有太大帮助)

4

2 回答 2

1

实现此目的的一种方法是使用UNIONand NOT 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

祝你好运。

于 2013-02-07T02:50:03.360 回答
0

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

我得到了所有的状态,并用第一个 LEFT JOIN 标记了哪些状态对给定的产品有效。

在第二个 LEFT JOIN 中,我获取了产品有效的所有状态并将其连接在一起。如果没有 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”

有任何想法吗?

于 2013-02-07T19:24:00.897 回答