我只有一个表:产品
ID | Product Name | Code 1 | Code 2 | Code 3
********************************************
1 | Phone1 | MM | DD | nd
2 | Phone2 | DD | | nd
3 | Phone3 | MM | ZZ | nd
4 | Phone4 | XX | | nd
我想:
选择其中一个代码与其中一个匹配的所有手机 Phone1 的代码但如果代码= ND
因此它应该返回 Phone2 和 Phone3 ,但现在它将全部返回。
我认为我应该使用这样的东西?但是不能正确地放置它:
WHERE NOT EXISTS
(SELECT p1.`Product Name`
FROM `products` p1
WHERE
p.`Product Name` = 'nd')
我相信在查找匹配项时,可以让MySQL更简单地排除每列中的某些值。
答案 0 :(得分:1)
让我们先回到“Phone1'”。我们可以轻松获得id
值,因此我们可以使用它。我们还可以使用product_name
列。
SELECT p.id
, p.product_name
, p.code_1
, p.code_2
, p.code_3
FROM products p
WHERE p.id = 1
很容易。
现在找到带有"匹配"的手机码。我们可以从加入products
表开始。
Phone1将在其中一个代码上匹配。 (假设至少有一个非NULL和非 - '代码。)我们假设我们不想返回Phone1,所以我们可以排除在连接谓词中...仅返回id
值不同的行。
要查找匹配代码,我们可以将候选手机中的code_1与Phone1的code_1,code_2和code_3进行比较,看看其中任何一个是否相同。我们可以为候选电话的code_2和code_3做同样的事情。
规范确实告诉我们nd
不会被视为匹配代码,因此我们可以快速进行比较,如果我们进行比较的code_N等于' nd'
从规范中,我们不清楚是否要考虑空字符串或空白,以等于空白或空字符串的另一个代码。 (我们无法判断这些空代码是否为NULL值,零长度字符串或空格。)
而且,显然,我们想要从"匹配"中返回列。电话,而不是Phone1行。
这样的事情可以解决问题:
SELECT o.id
, o.product_name
, o.code_1
, o.code_2
, o.code_3
FROM products p
JOIN products o
ON o.id <> p.id
AND ( (o.code_1 <> 'nd' AND o.code_1 IN (p.code_1,p.code_2,p.code_3) )
OR (o.code_2 <> 'nd' AND o.code_2 IN (p.code_1,p.code_2,p.code_3) )
OR (o.code_3 <> 'nd' AND o.code_3 IN (p.code_1,p.code_2,p.code_3) )
)
WHERE p.id = 1
使用连接谓词中的条件,o.code_N中的NULL
值不会与p.code_N中的NULL
值匹配。如果我们也想忽略空字符串的匹配,我们可以稍微调整一下条件:
AND ( (o.code_1 NOT IN ('nd','') AND o.code_1 IN (p.code_1,p.code_2,p.code_3) )
OR (o.code_2 NOT IN ('nd','') AND o.code_2 IN (p.code_1,p.code_2,p.code_3) )
OR (o.code_3 NOT IN ('nd','') AND o.code_3 IN (p.code_1,p.code_2,p.code_3) )
)
在表现方面,这可能不会赢得任何比赛。
这不是唯一会返回指定结果的查询模式。我们可以编写一个使用EXISTS
子句的查询来完成同样的事情:
SELECT o.id
, o.product_name
, o.code_1
, o.code_2
, o.code_3
FROM products o
WHERE EXISTS
( SELECT 1
FROM phones p
WHERE p.id = 1
AND o.id <> p.id
AND ( (o.code_1 <> 'nd' AND o.code_1 IN (p.code_1,p.code_2,p.code_3) )
OR (o.code_2 <> 'nd' AND o.code_2 IN (p.code_1,p.code_2,p.code_3) )
OR (o.code_3 <> 'nd' AND o.code_3 IN (p.code_1,p.code_2,p.code_3) )
)
)
如果有适当的索引,我们可以重写(可能)更高效。
就更简单的事情而言,如果电话的Code 1
,Code 2
和Code 3
在另一个表中存储为单独的行,则SQL的编写方式会有所不同:
phone_code
phone_id code_num code_val
1 1 MM
1 2 DD
1 3 nd
2 1 DD
2 2
2 3 nd
3 1 MM
3 2 ZZ
3 3 nd
4 1 XX
4 2
4 3 nd
如果数据的结构是这样的,那么SQL代码就会有所不同。