【问题标题】:MySQL value near by, join, abs with dynamic valueMySQL 值附近、连接、abs 与动态值
【发布时间】:2018-07-04 20:47:08
【问题描述】:

目标是获取最接近的 m3 数量和重量的价格并将其放在表格中。

此示例适用于我。但我硬编码m3,weight,countrytransportername

查询1:

SELECT
  country,
  transportername,
  ABS(m3-0.5) as ABS_M3 ,
  m3,
  ABS(weight-5) as ABS_weight,
  weight,
  price
FROM database.transportcost
WHERE   m3      >= 0.5    AND
        weight  >= 5      AND
        country = "GB"    AND
        transportername like '%aa%'
Group by transportername
Order by ABS(m3-0.5) +
         ABS(weight-5) +
         price

现在我想从另一个表中获取硬编码值。我不知道我需要在~~xx.volumen~~~~xx.gewicht~~ 中输入什么值。

查询2:

INSERT INTO database.transportcostPerItem (sku,country,transportname,weight,m3,price)
SELECT g.orderitemid, p2.country, p2.transportername, p2.weight, p2.m3, p2.price
FROM database.orderitem g
JOIN database.order i                 on i.orderid     = g.orderid
JOIN database.matrixtable xx       on g.orderitemid = xx.sku
JOIN database.vlog cc                on i.orderid     = cc.orderid
JOIN
(
  SELECT   *
  FROM database.transportcost
  Group by transportername
  Order by ABS(m3-~~xx.volumen~~) +
           ABS(weight-~~xx.gewicht~~) +
           price
) as p2 on p2.country          = i._country            AND
           p2.transportername  = cc._transportername   AND
           p2.weight           = xx.gewicht            AND
           p2.m3               = xx.volumen

;

编辑:

样本数据

表:database.transportcost 国家 |运输名称 |立方米 |重量 |价钱 --------+-----------------+--------+--------+------ --- 国标 |啊 | 50.00 | 50 | 77.70 国标 | bb | 0.50 | 125 | 83.19 国标 |抄送| 0.50 | 125 | 96.03 国标 | bb | 0.60 | 150 | 83.19 国标 |啊 | 75.00 | 75 | 89.04 国标 |抄送| 0.60 | 150 | 96.03 国标 | dd | 50.00 | 50 | 163.38 国标 |抄送| 0.70 | 175 | 96.03 国标 | bb | 0.70 | 175 | 96.85 国标 |呃 | 0.53 | 175 | 102.78 国标 | gg | 0.53 | 175 | 110.37 国标 |啊 | 100.00 | 100 | 89.04 国标 |抄送| 0.80 | 200 | 96.03 国标 | bb | 0.80 | 200 | 96.85 国标 | ff | 0.60 | 200 | 110.33 德 |啊! 0.50 | 50 | 26.40 德 | bbb | 0.50 | 75 | 31.84 德 |啊! 0.75 | 75 | 34.19 德 |抄送 | 0.50 | 100 | 34.17 德 | bbb | 0.67 | 100 | 35.47 德 |抄送 | 1.00 | 100 | 37.59 德 | dd | 0.50 | 100 | 62.38 德 |抄送 | 0.63 | 125 | 43.04 德 | bbb | 0.83 | 125 | 44.24 德 |啊! 0.93 | 125 | 45.84 德 | eee | 0.50 | 125 | 53.80 德 | ff | 0.50 | 125 | 54.02

Query 1 国家/地区的结果GB

国家 |运输名称 | ABS_M3 |立方米 | ABS_重量 |重量 |价钱 --------+-----------------+------------ +-------+------------+--------+-------- 国标 |啊 | 49.5 | 50.00 | 45 | 50 | 77.70 国标 | bb | 0 | 0.50 | 120 | 125 | 83.19 国标 |抄送| 0 | 0.50 | 120 | 125 | 96.03 国标 | dd | 49.5 | 50.00 | 45 | 50 | 163.38 国标 |呃 | 0.030000000000000027 | 0.53 | 170 | 175 | 102.78 国标 | gg | 0.030000000000000027 | 0.53 | 170 | 175 | 110.37

Query 1 国家/地区的结果DE

国家 |运输名称 | ABS_M3 |立方米 | ABS_重量 |重量 |价钱 --------+-----------------+--------+------+------- -----+--------+----- 德 |啊! 0 | 0.50 | 45 | 50 | 26.40 德 | bbb | 0 | 0.50 | 70 | 75 | 31.84 德 |抄送 | 0 | 0.50 | 95 | 100 | 34.17 德 | dd | 0 | 0.50 | 95 | 100 | 62.38 德 | eee | 0 | 0.50 | 120 | 125 | 53.80 德 | ff | 0 | 0.50 | 120 | 125 | 54.02 德 | ggg | 0 | 0.50 | 195 | 200 | 87.29

Query 2 最终的结果应该是这样的:

表:database.transportcostPerItem 订单项|国家 |运输名称 |立方米 |重量 |价钱 ------------+---------+-----------------+-----+--- -----+------ 1 |国标 |啊 | 0,5 | 5 | 77.70 2 |德 |啊! 0,5 | 5 | 26.40

【问题讨论】:

  • 样本数据和期望的结果真的很有帮助。一个明确的问题也会有所帮助。
  • @GordonLinoff 添加样本
  • 您的查询无效。您按 trasportername 分组,但不要告诉 DBMS 您想要获得什么聚合值。 MySQL 允许这种情况发生并任意选择值。例如,它可以为运输机 aa 选择 m3 = 100.00,重量 = 75,价格 = 77.70,这个结果将是有效的,因为您没有说您想要最大 m3 还是最小 m3 或任何一个。显然,DBMS 选择了 50.00 / 50 / 77.70 作为 transportername aa,但这是您不能依赖的随机结果。
  • @ThorstenKettner 你是对的,我应该在那里设置一个限制。顺便说一句,你是如何设计这样的结果表的?
  • 您的查询无法通过“限制”来修复。如果您按transportername 分组,那么您的选择列表必须只包含transportername 和聚合,例如min(m3)max(price)avg(weight) 等。您可能想SET sql_mode = 'ONLY_FULL_GROUP_BY' 以免让 MySQL 让此类查询被忽视。设置此模式后,您会收到一条错误消息,告诉您正在选择未由组或聚合函数指定的值。

标签: mysql sql


【解决方案1】:

您似乎只是在寻找给定 m3 和重量的最便宜的运输工具。在第一步中,您会找到至少给定 m3 和重量的所有运输工具。然后你选择其中最低的价格。

select *
from transportcost
where country = 'GB'
  and m3 >= 0.5
  and weight >= 5
order by price
limit 1;

如果您想要最接近给定 m3 和重量的措施,即使这种运输会更昂贵,您也可以按百分比的总和订购:

select *
from transportcost
where country = 'GB'
  and m3 >= 0.5
  and weight >= 5
order by m3 / 0.5 + weight / 5, price
limit 1;

现在,您可以从订单详细信息表中获取值,而不是给定 m3、重量、国家和运输商名称。如果这只是单个订单详细信息记录,则方法将完全相同,只是不与固定值 (m3 >= 0.5) 进行比较,而是与订单详细信息记录的值 (transportcost.m3 >= orderdetail.m3) 进行比较。唉,对于多个订单详细信息记录,这种方法不再适用,因为我们不能将结果限制为一行,而是每个订单详细信息记录需要一行。这可以通过标准 SQL 中的窗口函数(ROW_NUMBERRANK 等)或横向连接(CROSS APPLY)来解决。 MySQL 两者都没有。

以下是加入运输成本表的方法:

select *
from <your order tables>
join transportcost tc
where tc.country = i._country 
  and tc._transportername = cc._transportername 
  and tc.m3 >= xx.volumen
  and tc.weight >= xx.gewicht;

现在您必须找到一种方法来对您的结果进行排名,以便只获得每个订单详细信息的最佳匹配。一种方法是用变量模拟ROW_NUMBER。您可能想在其他答案中查找这一点。另一个是SELECT clause 中的限制子查询,但要使其工作,您需要一个标识运输成本表中记录的列。假设您添加了一个名为 ID 的列并用唯一值填充它...

select <some order columns>, tc.*
from
(
  select <some order columns>,
    (
      select id
      from transportcost tc
      where tc.country = i._country 
        and tc._transportername = cc._transportername 
        and tc.m3 >= xx.volumen
        and tc.weight >= xx.gewicht
      order by tc.m3 / xx.volumen + tc.weight / xx.gewicht, tc.price
      limit 1
    ) as best_transportcost_id
  from <your order tables>
) data
join transportcost tc
where tc.id = data.best_transportcost_id;

(您可以通过连接值以某种方式在没有 ID 的情况下执行此操作,例如“GB-aa-50.00-50-77.70”,以便有一个标识运输成本记录的字符串,但我不建议这样做。最好有一个带有索引的唯一 ID,以便快速查找。更好的是使用更好的 DBMS :-)

【讨论】:

  • 有些我怎么不能让它工作......我需要把连接放在哪里? ....FROM database.orderitem g JOIN database.order i on i.orderid = g.orderid JOIN database.matrixtable xx on g.orderitemid = xx.sku JOIN database.vlog cc on i.orderid = cc.orderid跨度>
  • 好吧,你会替换from &lt;your order tables&gt;。反正我不明白你的表:-) matrixtable 包含什么?由于它包含重量和体积,我宁愿期待一个item 表加入itemidvlog 包含订单的所有允许传输?或者为什么每个orderid 有多个vlog?了解这些表格会很有帮助。他们的主键是什么?它们代表什么?顺便说一句,似乎根本没有加入orders表的理由。
  • 这个不能正常工作..我删除了matrixtable..xx.gewicht成为的o._weightRealxx.volumen成为的o._m3..vlog有信息当有些东西正在发送.. Transportcost 有一个新字段id。没有真正的主键.. 它更像是一个 noslq 数据库。很难找到出路...
  • 到目前为止,我们还没有别名为 o 的表。你的意思是g = orderitem 可能吗?如果一个订单包含两个订单项 A 和 B,并且两个 vlog 与该订单相关,一个用于运输商 a,一个用于运输商 b,我们现在如何由哪个运输商运输哪个项目?
【解决方案2】:

我使用了@Thorsten 的解决方案。

这是结果

    INSERT INTO database.transportcostperitem (transportcostID, orderID, sku, country, transportername, weight, m3,price,shippingmethod,shippingstatus,shippingDate)
SELECT  
        transportcostID, 
        orderID,
        sku, 
        _country,
        transportername,
        transportTmp._weightReal,
        transportTmp._m3  ,
        price, 
        _shippingMethod,
        _shippingStatus,
        _shippingDate
FROM(

    SELECT 
        b.orderID,
        o.sku,      
        b.transporter,      
        o._country, 
        i._shippingMethod,
        i._shippingStatus,
        i._shippingDate,
        o._m3,
        o._weightReal,
        ( 

                SELECT  id
                FROM database.transportcost tc
                where
                    tc.transportername      = b._transporterName    AND
                    tc.country              = o._country            AND
                    tc.weight               >= o._weightReal        AND 
                    tc.m3                   >= o._m3
                order by    o._m3 / tc.m3  +  o._weightReal / tc.weight , tc.price
                limit 1

        ) as transportcostID
    FROM database.orderitem             o
    JOIN database.order                 i       on i.orderID = o.orderID 
    JOIN database.vlog                  b       on b.orderID = o.orderID    
    WHERE sku >0 

)as transportTmp
JOIN database.transportcost tc
where   tc.id = transportcostID     AND
        _shippingMethod is not null
orderID by sku
;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-04
    • 2015-11-29
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 2018-06-24
    • 1970-01-01
    相关资源
    最近更新 更多