我有一个非常具体的问题,我一直在努力争取解决它没有运气。
基本上,我想要实现的是根据货币价值从定价表'product_line_price'中获得最低价格。诀窍在于product_line_price表并不总是包含特定货币的值,在这种情况下,它必须默认选择默认的“AUD”货币。此表还包含每个产品的多个记录,具有不同的定价方案,但我只对我所查询的特定货币的最便宜(最低价格)感兴趣。
最终目标用于产品的“分面搜索”,用户可以选择价格范围来列出特定范围内的产品。
这是我尝试的整体查询,我认为这是最接近的尝试:
SELECT *
FROM product_line
LEFT JOIN
(
SELECT idproduct_line,
idprice_group,
CASE
WHEN EXISTS
(
SELECT currency_code
FROM product_line_price
WHERE currency_code = 'GBP'
AND idproduct_line = product_line_price.idproduct_line) THEN Min(price)
ELSE Min(price)*0.5098
END AS userprice
FROM product_line_price
WHERE !deleted
AND
CASE
WHEN EXISTS
(
SELECT currency_code
FROM product_line_price
WHERE currency_code = 'GBP'
AND idproduct_line = product_line_price.idproduct_line) THEN currency_code = 'GBP'
ELSE currency_code = 'AUD'
END
GROUP BY idproduct_line
ORDER BY product_line_price.idproduct_line ASC) AS product_line_price
ON product_line.idproduct_line = product_line_price.idproduct_line
WHERE !product_line.deleted
AND product_line.idproduct_line_status = 1
AND product_line.idproduct_line IN
(
SELECT `idproduct_line`
from `product_line_has_product_category`
where `idproduct_category` = '103')
AND ((
product_line_price.idprice_group IN
(
SELECT `idprice_group`
FROM `price_group`
WHERE !`deleted`
AND `PUBLIC`
AND `active`))
AND (
userprice <= 250))
ORDER BY product_line.idproduct_line ASC
我遇到问题的子查询就是这个:
SELECT idproduct_line,
idprice_group,
CASE
WHEN EXISTS
(
SELECT currency_code
FROM product_line_price
WHERE currency_code = 'GBP'
AND idproduct_line = product_line_price.idproduct_line) THEN Min(price)
ELSE Min(price)*0.5098
END AS userprice
FROM product_line_price
WHERE !deleted
AND
CASE
WHEN EXISTS
(
SELECT currency_code
FROM product_line_price
WHERE currency_code = 'GBP'
AND idproduct_line = product_line_price.idproduct_line) THEN currency_code = 'GBP'
ELSE currency_code = 'AUD'
END
GROUP BY idproduct_line
ORDER BY product_line_price.idproduct_line ASC
因此,我需要能够检索GBP货币的值(如果存在),否则默认为AUD货币(并应用货币转换)。这里的一些数字是用于测试的硬编码,稍后将通过变量提供。
我有一种感觉,使用上面的子查询,EXISTS子查询没有正确使用idproduct_line值,因为当我运行它时,我只获得GBP结果,即使该表中有大量记录没有GBP结果。我正在谈论的子查询就是这个:
SELECT currency_code
FROM product_line_price
WHERE currency_code = 'GBP'
AND idproduct_line = product_line_price.idproduct_line
谁能看到我哪里出错了?我觉得我很亲密,但是那个子查询中的某些内容是错误的,而SQL并不是我最强的套装。
我主要关心的是包含EXISTS子句的子查询,我知道其余部分都可以工作,并且纯粹为了上下文目的提供了整个查询。
您可以从以下链接下载有问题的表的转储和一些示例数据。样本数据包含3种产品的定价,一种仅具有AUD定价,一种具有AUD和GBP定价,另一种具有多种货币定价。 https://www.dropbox.com/s/h1i23f5ac2jmrvn/product_line_price.sql?dl=0
我针对此数据运行的查询是:
SELECT idproduct_line,
idprice_group,
currency_code,
CASE
WHEN EXISTS
(
SELECT currency_code
FROM product_line_price_2
WHERE currency_code = 'GBP'
AND idproduct_line = product_line_price_2.idproduct_line AND !deleted) THEN Min(price)
ELSE Min(price)*0.5098
END AS userprice
FROM product_line_price_2
WHERE !deleted
AND
CASE
WHEN EXISTS
(
SELECT currency_code
FROM product_line_price_2
WHERE currency_code = 'GBP'
AND idproduct_line = product_line_price_2.idproduct_line AND !deleted) THEN currency_code = 'GBP'
ELSE currency_code = 'AUD'
END
GROUP BY idproduct_line
ORDER BY product_line_price_2.idproduct_line ASC
我的预期输出是3条记录,2条显示最低价格的英镑价格,另一条显示最低价格的澳元定价,转换为英镑(通过查询中的'* 0.5098')。
我看到的实际产量只有2条带有英镑定价的记录,因此它忽略了澳元的定价。
答案 0 :(得分:0)
尽我所能了解并使用您现有的代码,您可以尝试:
SELECT *
FROM
product_line
LEFT JOIN (
SELECT
idproduct_line,
idprice_group,
CASE
WHEN EXISTS (
SELECT
currency_code
FROM
product_line_price
WHERE
currency_code = 'GBP'
AND idproduct_line = product_line_price.idproduct_line
) THEN
MIN(price)
ELSE
MIN(price) * 0.5098
END AS userprice
FROM
product_line_price
WHERE
deleted = 0
AND CASE WHEN EXISTS (
SELECT
currency_code
FROM
product_line_price
WHERE
currency_code = 'GBP'
AND idproduct_line = product_line_price.idproduct_line
) THEN
currency_code = 'GBP'
ELSE
currency_code = 'AUD'
END
GROUP BY
idproduct_line
ORDER BY
idproduct_line ASC
) AS product_line_price ON product_line.idproduct_line = product_line_price.idproduct_line
WHERE
product_line.deleted = 0
AND product_line.idproduct_line_status = 1
AND product_line.idproduct_line IN (
SELECT
idproduct_line
FROM
product_line_has_product_category
WHERE
idproduct_category = '103'
)
AND product_line_price.idprice_group IN (
SELECT idprice_group
FROM price_group
WHERE
!deleted
AND PUBLIC
AND active
AND userprice <= 250
)
ORDER BY
product_line.idproduct_line ASC;
试试这个:
SELECT
pl.*,
IF(plp.currency_code = 'GBP', MIN(IFNULL(plp.price, 0)), MIN(IFNULL(plp.price, 0)) * 0.5098)
FROM
product_line pl
LEFT JOIN product_line_price plp ON plp.idproduct_line = pl.idproduct_line
WHERE
!pl.deleted
AND !plp.deleted
AND plp.currency_code IN ('GBP','AUD')
AND pl.idproduct_line_status = 1
AND pl.idproduct_line IN (
SELECT
idproduct_line
FROM
product_line_has_product_category
WHERE
idproduct_category = '103'
)
AND plp.idprice_group IN (
SELECT idprice_group
FROM price_group
WHERE
!deleted
AND public = 1
AND active
AND userprice <= 250
)
ORDER BY
pl.idproduct_line ASC;
最后,请试试这个:
SELECT
pl.*,
plp.idproduct_line,
plp.idprice_group
IF(plp.currency_code = 'GBP', MIN(IFNULL(plp.price, 0)), MIN(IFNULL(plp.price, 0)) * 0.5098)
FROM
product_line pl
LEFT JOIN product_line_price plp ON plp.idproduct_line = pl.idproduct_line
LEFT JOIN product_line_has_product_category plhpc ON plhpc.idproduct_line = pl.idproduct_line
LEFT JOIN price_group pg ON pg.idprice_group = plp.idprice_group
WHERE
pl.deleted = 0
AND pl.idproduct_line_status = 1
AND plp.deleted = 0
AND plp.currency_code IN ('GBP','AUD')
AND plhpc.idproduct_category = '103'
AND !pg.deleted
AND pg.public
AND pg.active
AND pg.userprice <= 250
ORDER BY
pl.idproduct_line ASC;
答案 1 :(得分:0)
经过长时间的斗争和工作同事的帮助,我们采取了不同的方法,找到了解决这个问题的方法。
SELECT product_line.idproduct_line,
Min(local_price.price) local_userprice,
Min(fallback_price.price) fallback_userprice
FROM product_line
INNER JOIN product_line_has_product_category
ON product_line.idproduct_line =
product_line_has_product_category.idproduct_line
AND 103 = product_line_has_product_category.idproduct_category
LEFT JOIN (product_line_price local_price
INNER JOIN price_group local_price_group
ON local_price.idprice_group =
local_price_group.idprice_group
AND ! local_price_group.deleted
AND local_price_group.PUBLIC
AND local_price_group.active)
ON product_line.idproduct_line = local_price.idproduct_line
AND 'GBP' = local_price.currency_code
LEFT JOIN (product_line_price fallback_price
INNER JOIN price_group fallback_price_group
ON fallback_price.idprice_group =
fallback_price_group.idprice_group
AND ! fallback_price_group.deleted
AND fallback_price_group.PUBLIC
AND fallback_price_group.active)
ON product_line.idproduct_line = fallback_price.idproduct_line
AND 'AUD' = fallback_price.currency_code
WHERE ! product_line.deleted
AND product_line.idproduct_line_status = 1
GROUP BY product_line.idproduct_line
HAVING ( local_userprice IS NULL
AND fallback_userprice <= 250 )
OR ( local_userprice <= 250 )
ORDER BY product_line.idproduct_line ASC
使用连接,交叉引用GBP和AUD的值(这给同一行中的价格和货币提供了2列)..然后我们可以使用HAVING子句比较每列,结果是成功的! / p>