【发布时间】:2017-08-28 18:25:20
【问题描述】:
我正在尝试匹配两个表,其中一个表将多个值存储为字符串。
在下面的示例中,我需要使用 #NewProduct.NewProductId 对从 #Orders 表中订购的每个产品进行分类。
我遇到的问题是有时我们会推出一款新产品,例如“Black Shirt”, 后来我们推出了对该产品的改编,例如“Black Shirt Vneck”。
我需要将这两个更改正确匹配到#Orders 表。因此,如果订单有黑色和衬衫,但没有 Vneck,则视为“黑色衬衫”,但如果订单有黑色和衬衫和 Vneck,则视为“黑色 Vneck 衬衫”。
下面的代码是一个示例 - 我正在使用的当前逻辑返回具有左连接的重复项。 另外,假设我们可以修改#NewProducts 的格式,但不能修改#Orders。
IF OBJECT_ID('tempdb.dbo.#NewProducts') IS NOT NULL DROP TABLE #NewProducts
CREATE TABLE #NewProducts
(
ProductType VARCHAR(MAX)
, Attribute_1 VARCHAR(MAX)
, Attribute_2 VARCHAR(MAX)
, NewProductId INT
)
INSERT #NewProducts
VALUES
('shirt', 'black', 'NULL', 1),
('shirt', 'black', 'vneck', 2),
('shirt', 'white', 'NULL', 3)
IF OBJECT_ID('tempdb.dbo.#Orders') IS NOT NULL DROP TABLE #Orders
CREATE TABLE #Orders
(
OrderId INT
, ProductType VARCHAR(MAX)
, Attributes VARCHAR(MAX)
)
INSERT #Orders
VALUES
(1, 'shirt', 'black small circleneck'),
(2, 'shirt', 'black large circleneck'),
(3, 'shirt', 'black small vneck'),
(4, 'shirt', 'black small vneck'),
(5, 'shirt', 'white large circleneck'),
(6, 'shirt', 'white small vneck')
SELECT *
FROM #Orders o
LEFT JOIN #NewProducts np
ON o.ProductType = np.ProductType
AND CHARINDEX(np.Attribute_1, o.Attributes) > 0
AND (
CHARINDEX(np.Attribute_2, o.Attributes) > 0
OR np.Attribute_2 = 'NULL'
)
【问题讨论】:
-
这不会有好的结局。规范化您的数据,否则您将陷入字符串匹配地狱(甚至不考虑所有错误和所有性能问题)。你可以有一个
PRODUCTS、一个PRODUCT_ATTRIBUTES和一个ATTRIBUTES表,然后根据SELECT * FROM orders INNER JOIN products ON orders.product = products.id AND EXISTS (SELECT 1 FROM product_attributes INNER JOIN attributes ON product_attributes.product = attributes.id WHERE product_attributes.product = products.id AND attributes.name = "Black") AND EXISTS (SELECT 1 ... WHERE attributes.name = "Vneck")做一些事情 -
这将是理想的,但我受工程团队的摆布,他们将属性字段存储为单个字符串。我可以通过拆分字符串来制作一个临时#attributes 表,然后使用您的方法。这行得通吗?
-
不是对您问题的回答,而只是评论。因为您在
NULL周围加上了引号,所以您将在相关位置插入单词“NULL”。这不是NULL的用途。您可以不加引号,但您还需要对查找NULLs 的代码进行相应更改。 -
两个直接的问题:“其中一个表将多个值存储为字符串”和“使用空值连接字段”即您的数据违反了 1NF,这是关系模型的最基本要求和编写能力一个简单的 SQL 查询(选择的答案证实了这一点)。要求您的工程团队做得更好!
标签: sql join string-matching