SQL 服务器:使用多个 AND 和 OR 进行内部联接
SQL Server : inner join with multiple ANDs and ORs
每个产品都有 LatLng
。随着时间的推移,有时产品可以复制,但很难发现。价格或图片可能略有不同。
我想比较 Products
每个位置的 ProductType
和 Price
并将它们放在地图上以便更容易找到重复项。
对于每个产品,我计算其价格的 5%,这样我就可以 add/subtract 从其他产品价格中找到大致匹配的。
Products
ProductID
ProductType
Price
Latitude
Longitude
ABC
Red Widget
500
12.34
67.89
DEF
Red Widget
505
12.34
67.89
MNO
Red Widget
480
12.34
67.89
RST
Red Widget
500
12.34
67.89
UVW
Red Widget
300
12.34
67.89
JKL
Blue Widget
800
76.54
32.10
XYZ
Blue Widget
800
45.67
23.45
预期的结果是应该返回ABC
、DEF
、MNO
AND RST
,因为它们都是Red Widgets
,在同一个位置和价格要么完全相同,要么价格相差在彼此价格的 5% 以内。
UVW
超出百分比,因此可能不是重复项,不应返回。
JKL
和 XYZ
是 Blue Widgets
价格相同,但不在同一地点,因此不退货。
SQL
这是我目前所拥有的,但它返回的结果太多了。我认为它会返回在每个位置之外匹配的行。 JOIN 中的 AND 在我看来是正确的。感觉 OR 可能允许更灵活的匹配,但括号看起来正确...
WITH cte AS
(
SELECT
p.ProductID,
p.ProductType,
p.Price,
(p.Price / 100) * 5 AS PricePercent,
ROUND(p.Latitude, 3) AS Latitude,
ROUND(p.Longitude, 3) AS Longitude
FROM
Products p
WHERE
p.Latitude IS NOT NULL AND p.Longitude IS NOT NULL
)
SELECT
DISTINCT a.ProductID,
a.Price,
a.Latitude, a.Longitude
FROM
cte a
INNER JOIN
/* ProductIDs don't match */
cte b ON a.ProductID <> b.ProductID
/* match only where location is the same*/
AND a.Latitude = b.Latitude
AND a.Longitude = b.Longitude
/* match only where Product Type is the same*/
AND a.ProductType = b.ProductType
/*match only if price is the same, or within 5% above or 5% below price*/
AND (/*same price*/
b.Price = a.Price
OR
/*b.price is within percentage over a.price*/
(b.Price > a.Price AND b.Price < (a.Price+a.PricePercent))
OR
/*b.price is within percentage under a.price */
(b.Price < a.Price AND b.Price >(a.Price-a.PricePercent)))
首先这件事:
AND (/*same price*/
b.Price = a.Price
OR
/*b.price is within percentage over a.price*/
(b.Price > a.Price AND b.Price < (a.Price+a.PricePercent))
OR
/*b.price is within percentage under a.price */
(b.Price < a.Price AND b.Price >(a.Price-a.PricePercent))
)
与(或应该)相同:
AND (
-- price within range +/- percent
b.Price < (a.Price+a.PricePercent)
AND b.Price >(a.Price-a.PricePercent)
)
其次对我有用:
MS SQL Server 2017 架构设置:
查询 1:
WITH cte AS
(
SELECT
p.ProductID,
p.ProductType,
p.Price,
(p.Price / 100) * 5 AS PricePercent,
ROUND(p.Latitude, 3) AS Latitude,
ROUND(p.Longitude, 3) AS Longitude
FROM
Products p
WHERE
p.Latitude IS NOT NULL AND p.Longitude IS NOT NULL
)
SELECT
DISTINCT a.ProductID,
a.Price,
a.Latitude, a.Longitude
FROM
cte a
INNER JOIN
/* ProductIDs don't match */
cte b ON a.ProductID <> b.ProductID
/* match only where location is the same*/
AND a.Latitude = b.Latitude
AND a.Longitude = b.Longitude
/* match only where Product Type is the same*/
AND a.ProductType = b.ProductType
/*match only if price is the same, or within 5% above or 5% below price*/
AND (
-- price within range +/- percent
b.Price < (a.Price+a.PricePercent)
AND b.Price >(a.Price-a.PricePercent)
)
ProductID
Price
Latitude
Longitude
ABC
500
12
68
DEF
505
12
68
RST
500
12
68
每个产品都有 LatLng
。随着时间的推移,有时产品可以复制,但很难发现。价格或图片可能略有不同。
我想比较 Products
每个位置的 ProductType
和 Price
并将它们放在地图上以便更容易找到重复项。
对于每个产品,我计算其价格的 5%,这样我就可以 add/subtract 从其他产品价格中找到大致匹配的。
Products
ProductID | ProductType | Price | Latitude | Longitude |
---|---|---|---|---|
ABC | Red Widget | 500 | 12.34 | 67.89 |
DEF | Red Widget | 505 | 12.34 | 67.89 |
MNO | Red Widget | 480 | 12.34 | 67.89 |
RST | Red Widget | 500 | 12.34 | 67.89 |
UVW | Red Widget | 300 | 12.34 | 67.89 |
JKL | Blue Widget | 800 | 76.54 | 32.10 |
XYZ | Blue Widget | 800 | 45.67 | 23.45 |
预期的结果是应该返回ABC
、DEF
、MNO
AND RST
,因为它们都是Red Widgets
,在同一个位置和价格要么完全相同,要么价格相差在彼此价格的 5% 以内。
UVW
超出百分比,因此可能不是重复项,不应返回。
JKL
和 XYZ
是 Blue Widgets
价格相同,但不在同一地点,因此不退货。
SQL
这是我目前所拥有的,但它返回的结果太多了。我认为它会返回在每个位置之外匹配的行。 JOIN 中的 AND 在我看来是正确的。感觉 OR 可能允许更灵活的匹配,但括号看起来正确...
WITH cte AS
(
SELECT
p.ProductID,
p.ProductType,
p.Price,
(p.Price / 100) * 5 AS PricePercent,
ROUND(p.Latitude, 3) AS Latitude,
ROUND(p.Longitude, 3) AS Longitude
FROM
Products p
WHERE
p.Latitude IS NOT NULL AND p.Longitude IS NOT NULL
)
SELECT
DISTINCT a.ProductID,
a.Price,
a.Latitude, a.Longitude
FROM
cte a
INNER JOIN
/* ProductIDs don't match */
cte b ON a.ProductID <> b.ProductID
/* match only where location is the same*/
AND a.Latitude = b.Latitude
AND a.Longitude = b.Longitude
/* match only where Product Type is the same*/
AND a.ProductType = b.ProductType
/*match only if price is the same, or within 5% above or 5% below price*/
AND (/*same price*/
b.Price = a.Price
OR
/*b.price is within percentage over a.price*/
(b.Price > a.Price AND b.Price < (a.Price+a.PricePercent))
OR
/*b.price is within percentage under a.price */
(b.Price < a.Price AND b.Price >(a.Price-a.PricePercent)))
首先这件事:
AND (/*same price*/
b.Price = a.Price
OR
/*b.price is within percentage over a.price*/
(b.Price > a.Price AND b.Price < (a.Price+a.PricePercent))
OR
/*b.price is within percentage under a.price */
(b.Price < a.Price AND b.Price >(a.Price-a.PricePercent))
)
与(或应该)相同:
AND (
-- price within range +/- percent
b.Price < (a.Price+a.PricePercent)
AND b.Price >(a.Price-a.PricePercent)
)
其次对我有用:
MS SQL Server 2017 架构设置:
查询 1:
WITH cte AS
(
SELECT
p.ProductID,
p.ProductType,
p.Price,
(p.Price / 100) * 5 AS PricePercent,
ROUND(p.Latitude, 3) AS Latitude,
ROUND(p.Longitude, 3) AS Longitude
FROM
Products p
WHERE
p.Latitude IS NOT NULL AND p.Longitude IS NOT NULL
)
SELECT
DISTINCT a.ProductID,
a.Price,
a.Latitude, a.Longitude
FROM
cte a
INNER JOIN
/* ProductIDs don't match */
cte b ON a.ProductID <> b.ProductID
/* match only where location is the same*/
AND a.Latitude = b.Latitude
AND a.Longitude = b.Longitude
/* match only where Product Type is the same*/
AND a.ProductType = b.ProductType
/*match only if price is the same, or within 5% above or 5% below price*/
AND (
-- price within range +/- percent
b.Price < (a.Price+a.PricePercent)
AND b.Price >(a.Price-a.PricePercent)
)
ProductID | Price | Latitude | Longitude |
---|---|---|---|
ABC | 500 | 12 | 68 |
DEF | 505 | 12 | 68 |
RST | 500 | 12 | 68 |