SELECT
*,
p.name AS name,
p.image,
p.price,
(
SELECT ps.price
FROM product_special ps
WHERE p.id = ps.id
AND ps.date < NOW()
ORDER BY ps.priority ASC, LIMIT 1
) AS special_price,
(
SELECT ps.date
FROM product_special ps
WHERE p.id = ps.id
AND ps.date < NOW()
ORDER BY ps.priority ASC, LIMIT 1
) AS date
FROM product p LEFT JOIN product_special ps ON (p.id = ps.id)
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我重复相同的子查询只是为了得到另一列。我想知道有没有更好的方法来做到这一点?
id是两个表中的主键。如果有帮助,我可以让product_special.priority变得独一无二。
a1e*_*x07 15
假设组合product_special.id, product_special.priority是唯一的
SELECT p.*, special_price,special_date
FROM product p
LEFT JOIN
(
SELECT ps.id, ps.price as special_price, ps.`date` as special_date
FROM product_special ps
INNER JOIN
(
SELECT id, MIN(priority) as min_priority
FROM product_special
GROUP BY id
) ps2
ON (ps2.id = ps.id)
)a ON (a.id=p.id)
Run Code Online (Sandbox Code Playgroud)
小智 10
受到 dezso 的回答https://dba.stackexchange.com/a/222471/127433的启发 ,我正在使用数组解决 PostgreSQL 中的问题,如下所示:
SELECT
*,
p.name AS name,
p.image,
p.price,
(
SELECT ARRAY[ps.price, ps.date]
FROM product_special ps
WHERE p.id = ps.id
AND ps.date < NOW()
ORDER BY ps.priority ASC, LIMIT 1
) AS special_price_and_date
FROM product p LEFT JOIN product_special ps ON (p.id = ps.id)
Run Code Online (Sandbox Code Playgroud)
诚然,它仍然只是一列,但在我的代码中,我可以轻松访问这两个值。希望它也适合你。
除非您打算将字段作为 special_price.price 和 date.date 返回,为什么不在子查询中使用别名?例如
SELECT p.*, p.name AS name, p.image, p.price, ps.*
FROM product p
LEFT JOIN
(SELECT
psi.price as special_price, psi.date as my_date
FROM product_special psi
WHERE
p.id = psi.id AND
psi.date < NOW()
ORDER BY psi.priority ASC, LIMIT 1
) AS ps ON
p.id = ps.id
Run Code Online (Sandbox Code Playgroud)
您的查询语言是否具有 FIRST() 聚合函数?不确定是否可以使 product_special 的 PK 成为 id 和优先级(均为 ASC 排序)之间的组合并将 ORDER 子句更改为GROUP BY id, psi.priority
您可能能够完全删除 ORDER BY 子句并使用 HAVING MIN(psi.priority)
小智 5
请注意,SQL Server 中的“交叉应用”机制可以解决此问题,但在 PostgreSQL 中不可用。基本上,他们的解决方案是如何将参数(通常是对当前表表达式外部的列的引用)传递给 FROM 子句中称为表表达式的函数。但事实证明,它对于您想要避免另一级子查询嵌套或将内容从 FROM 子句移动到 SELECT 子句的各种情况都很有用。PostgreSQL 通过创建一种异常来实现这一点——如果表达式是一个简单的函数调用但严格来说不是一个嵌入式 SELECT,那么您可以传递这样的参数。所以
left join highestPriorityProductSpecial(p.id) on true
可以,但不行
left join (select * from product_special ps where ps.id = p.id order by priority desc limit 1) on true
即使函数的定义正是如此。
所以,这实际上是一个方便的解决方案(至少在 9.1 中):创建一个函数,通过在函数内部执行 limit 来提取最高优先级的行。
但函数有一个缺点,即查询计划不会显示它们内部发生的情况,我相信它总是会选择嵌套循环连接,即使这可能不是最好的。
小智 5
尝试以下 SQL 命令:
SELECT p.name,p.image,p.price,pss.price,pss.date
FROM Product p OUTER APPLY(SELECT TOP(1)*
FROM ProductSpecial ps
WHERE p.Id = ps.Id ORDER BY ps.priority )as pss
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
158661 次 |
| 最近记录: |