【发布时间】:2021-12-22 02:43:20
【问题描述】:
我已经在 Google 上进行了广泛的搜索和测试。我想我可能是大脑衰退了。
我们的网站有各种产品的特定登录页面。
Control 表保存页面标题和产品搜索信息。
Control
ID Title Category Colour
------------------------------------------------------------
1 Blue Postcards Postcard Blue
2 Blue Photos Photo Blue
3 Yellow Postcards Postcard Yellow
4 Postcards Postcard null
Products
pk_ProdID Category Price
-------------------------------------------
100 Postcard 59
200 Photo 42
300 Postcard 33
400 Photo 97
500 Postcard 78
600 Postcard 48
每个产品都有零个或多个可以出售的颜色的记录。
Products_Colours
fk_ProdID Colour
-------------------------
100 Blue
100 Yellow
200 Blue
300 Yellow
400 Red
500 Blue
500 Yellow
600 Blue
如果Control 的 ID 为 1,则页面应显示蓝色明信片。
以下是想要的结果:
ProdID Category Price
-------------------------------------------
100 Postcard 59
500 Postcard 78
600 Postcard 48
我实际上得到的是:
ProdID Category Price
-------------------------------------------
100 Postcard 59
100 Postcard 59
500 Postcard 78
500 Postcard 78
600 Postcard 48
SQL
此存储过程为我的 PHP 页面返回两个记录集,以减少对数据库的请求数。
DECLARE @OrderBy varchar(1)
SET @OrderBy = 'D'
DECLARE @Row int
SET @Row = 1
DECLARE @ControlID int
SET @Control = 1
/* get control info for web page */
SELECT
c.ID,
c.Title
FROM dbo.Control c
WHERE c.ID = @ControlID;
/* get search criteria */
WITH ControlSearch AS
(
SELECT
ID,
Category,
Colour
FROM Control WHERE ID = @ControlID
),
/* get products that match search criteria */
ProductSearch AS
(
SELECT
DISTINCT p.ProdID,
p.Category
Count(1) OVER() As Total_Records,
ROW_NUMBER() OVER(
ORDER BY
CASE WHEN @OrderBy = 'D' THEN p.Price END DESC,
CASE WHEN @OrderBy = 'U' THEN p.Price END ASC
) As RowNum
FROM dbo.Products p
JOIN ControlSearch l ON l.ID = @ControlID
LEFT JOIN dbo.Products_Colours co ON p.ProdID = co.ProdID
WHERE
(p.Category = l.Category)
AND
(co.Colour = l.Colour OR l.Colour is null)
)
/* return recordset */
SELECT * FROM ProductSearch WHERE RowNum >= @Row AND RowNum < (@Row + 50)
我向用户显示匹配记录的总数,并输出行号,以便我可以按 50 个产品分页。
为什么这会根据它有多少颜色返回多个产品?
【问题讨论】:
-
“为什么这会根据它有多少颜色返回多个产品?” 因为这就是连接的工作方式。如果您有 1 行与 2 行相关,并且您
JOIN1 行与 2 行相关,则您将获得 2 行。就像如果你有 2 行与 4 行相关,当你JOIN时你会得到 8 行。 -
为什么将子句
p.Category = l.Category和co.Colour = l.Colour放在WHERE中,而不是在JOINs 中放置适当的ON子句?例如,拥有JOIN ControlSearch l ON p.Category = l.Category然后拥有WHERE l.ID = @ControlID更有意义。 -
如何将其更改为每个匹配的产品仅返回 1 行?
-
-
这取决于您想要哪一个“每个产品 1 行”,为什么?为什么它应该选择蓝色而不是黄色,反之亦然?不要说没关系; SQL Server 没有
ARBITRARY功能。
标签: sql-server join left-join