如何解决隐式原始mysql查询转换为yii2查询2左连接子查询并求和全部
我已经在mysql中创建了原始查询,但运行正常。我正在尝试将其转换为yii2查询,但我无法完成它,谁能帮我
原始查询:
SELECT
ship.month_name,MIN(ship.average_value_percent) as minimum_container_utilization,MAX(ship.average_value_percent) as maximum_container_utilization,SUM(ship.average_value) / COUNT(ship.shipment) as volume,SUM(ship.average_weight) / COUNT(ship.shipment) as volume_kgs,SUM(ship.average_volume_cbm) / COUNT(ship.shipment) as volume_cbm,SUM(ship.average_value_percent) / COUNT(ship.shipment) as volume_percent
FROM
(
SELECT
sh.JS_UniqueConsignRef as shipment,SUM(sp.volume) as average_volume_cbm,SUM(sp.volume) / SUM(sc.teu) AS average_value,SUM(sp.volume) / SUM(sc.capacity) AS average_value_percent,SUM(sp.weight) as average_weight,date_format(sh.JS_E_ARV,'%b') AS month_name,if(
month(sh.JS_E_ARV) >= month(now()),month(sh.JS_E_ARV),month(sh.JS_E_ARV) + 12
) as months_order
FROM
ship_head sh
JOIN (
SELECT
SUM(RC_TEU) teu,SUM(RC_Cubiccapacity) capacity,ship_head_id,JC_ContainerMode,JC_ContainerNum
FROM
ship_container
GROUP BY
ship_head_id,JC_ContainerNum,JC_ContainerMode
) sc ON sc.ship_head_id = sh.sh_id
JOIN (
SELECT
SUM(JL_ActualVolume) volume,SUM(JL_ActualWeight) weight,JC_ContainerNum
FROM
ship_pack
GROUP BY
ship_head_id,JC_ContainerNum
) sp ON sp.ship_head_id = sh.sh_id
WHERE
sh.is_latest = 1
AND sp.JC_ContainerNum = sc.JC_ContainerNum
AND sc.JC_ContainerMode IN ('FCL','FTL')
AND sh.JS_E_ARV < NOW() - INTERVAL 1 MONTH
and sh.JS_E_ARV > Date_add(NOW() - INTERVAL 1 MONTH,interval - 12 month)
GROUP BY
sh.sh_id
) AS ship
GROUP BY
ship.month_name,ship.months_order
ORDER BY
ship.months_order
Yii2查询
$shipContainerQuery = ShipContainer::find()
->select(['SUM(RC_TEU) AS teu','SUM(RC_Cubiccapacity) AS capacity','ship_head_id','JC_ContainerMode','JC_ContainerNum'])
->groupBy('ship_head_id','JC_ContainerNum','JC_ContainerMode')
->all();
$shipPackQuery = ShipPack::find()
->select(['UM(JL_ActualVolume) AS volume','SUM(JL_ActualWeight) AS weight','JC_ContainerNum')
->all();
$shipHeadQuery = ShipHead::find()
->select(['sh.JS_UniqueConsignRef AS shipment','SUM(sp.volume) AS average_volume_cbm','SUM(sp.volume) / SUM(sc.teu) AS average_value','SUM(sp.volume) / SUM(sc.capacity) AS average_value_percent','SUM(sp.weight) AS average_weight','date_format(sh." . $filterField . ",'%b') AS month_name','if(month(sh." . $filterField . ")>=month(now()),month(sh." . $filterField . "),month(sh." . $filterField . ")+12) as months_order)'])
->from(ShipHead::tableName() .' AS sh')
->leftJoin(['sc' => $shipContainerQuery],"sc.ship_head_id = sh.sh_id AND sc.JC_ContainerMode IN ('FCL','FTL')")
->leftJoin(['sp' => $shipPackQuery],'sp.ship_head_id = sh.sh_id AND sp.JC_ContainerNum = sc.JC_ContainerNum')
->where(['sh.is_latest' => 1])
->andWhere('sh.JS_E_ARV < NOW() - INTERVAL 1 MONTH and sh.JS_E_ARV > Date_add(NOW() - INTERVAL 1 MONTH,interval - 12 month)')
->groupBy('sh.sh_id');
$shipQuery = $shipQuery
->addSelect(["SUM(ship.average_value) / COUNT(ship.shipment) AS volume","'teu' as volume_unit","SUM(ship.average_value_percent) / COUNT(ship.shipment) AS average_container_utilization"])
解决方法
代码的主要问题是,您正在子查询中调用all()
方法。因此,您可以将它们的结果传递到另一个查询中,而不是将它们作为查询传递。
另一个问题是,在您的php代码中,您正在使用leftJoin
,但在原始SQL中,您有JOIN
,这意味着INNER JOIN
。
通过groupBy()
指定多列时,您需要使用数组。
您可能希望将更复杂的表达式包装在\yii\db\Expression
实例中,以防止Yii在尝试引用表名或列时弄乱您的表达式。
您还可以使用$shipHeadQuery->alias('sh')
代替$shipHeadQuery->from(ShipHead::tableName() .' AS sh')
向ActiveQuery添加别名。
您可以使用数组为所选列指定别名,以提高可读性。
整个查询可能看起来像这样
//Add following two lines to the other use clauses if they are not already there.
use \yii\db\Expression;
use \yii\db\Query;
$shipContainerQuery = ShipContainer::find()
->select([
'teu' => new Expression('SUM(RC_TEU)'),'capacity' => new Expression('SUM(RC_Cubiccapacity)'),'ship_head_id','JC_ContainerMode','JC_ContainerNum',])->groupBy(['ship_head_id','JC_ContainerMode']);
$shipPackQuery = ShipPack::find()
->select([
'volume' => new Expression('SUM(JL_ActualVolume)'),'weight' => new Expression('SUM(JL_ActualWeight)'),'JC_ContainerNum']);
$shipHeadQuery = ShipHead::find()
->select([
'shipment' => 'sh.JS_UniqueConsignRef','average_volume_cbm' => new Expression('SUM(sp.volume)'),'average_value' => new Expression('SUM(sp.volume) / SUM(sc.teu)'),'average_value_percent' => new Expression('SUM(sp.volume) / SUM(sc.capacity)'),'average_weight' => new Expression('SUM(sp.weight)'),'month_name' => new Expression("date_format(sh.JS_E_ARV,'%b')"),'months_order' => new Expression('if(month(sh.JS_E_ARV) >= month(now()),month(sh.JS_E_ARV),month(sh.JS_E_ARV) + 12)'),])->alias('sh')
->innerJoin(['sc' => $shipContainerQuery],'sc.ship_head_id = sh.sh_id')
->innerJoin(['sp' => $shipPackQuery],'sp.ship_head_id = sh.sh_id')
->where(['sh.is_latest' => 1])
->andWhere('sp.JC_ContainerNum = sc.JC_ContainerNum')
->andWhere(['in','sc.JC_ContainerMode',['FCL','FTL']])
->andWhere(new Expression('sh.JS_E_ARV < NOW() - INTERVAL 1 MONTH'))
->andWhere(new Expression('sh.JS_E_ARV > Date_add(NOW() - INTERVAL 1 MONTH,interval - 12 month)')
->groupBy('sh.sh_id');
$shipQuery = new Query()
->select([
'ship.month_name','minimum_container_utilization' => new Expression('MIN(ship.average_value_percent)'),'maximum_container_utilization' => new Expression('MAX(ship.average_value_percent)'),'volume' => new Expression('SUM(ship.average_value) / COUNT(ship.shipment)'),'volume_kgs' => new Expression('SUM(ship.average_weight) / COUNT(ship.shipment)'),'volume_cbm' => new Expression('SUM(ship.average_volume_cbm) / COUNT(ship.shipment)'),'volume_percent' => new Expression('SUM(ship.average_value_percent) / COUNT(ship.shipment)'),])->from(['ship' => $shipHeadQuery])
->groupBy(['ship.month_name','ship.months_order'])
->orderBy(['ship.months_order' => SORT_ASC]);
然后,您可以通过调用$shipQuery->all()
获得结果,也可以在需要的地方使用查询。
因为我没有数据库结构,所以没有测试查询。可能有错别字,或者查询可能需要调试。
,我建议您仅使用DAO来消除复杂性,将其转换为yii2查询不是一个好主意。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。