检查子查询结果是否存在,然后减去它

Check if subquery result exists and then subtract it

我有一个大查询,我必须减去子查询值。我尝试了 JOINS,但它们无法正常工作,因为有多个分组会导致不正确的数学方程式结果。查询:

SELECT 
o.order_id, 
sa.shipping_name AS user, 
ROUND(SUM(op.price * op.amount) + o.shipping_price - IF(EXISTS(SELECT SUM(od.discount) FROM order_discounts od WHERE od.order_id=o.order_id GROUP BY od.order_id), (SELECT SUM(od.discount) FROM order_discounts od WHERE od.order_id=o.order_id GROUP BY od.order_id), 0), 2) 

AS order_total FROM 
( orders o JOIN order_products op ON op.order_id=o.order_id ) 
LEFT OUTER JOIN shipping_addresses sa ON o.shipping_address_id = sa.shipping_address_id 
GROUP BY o.order_id ORDER BY o.order_date DESC, o.user_id DESC

如您所见,我必须 运行 查询以检查是否有折扣,然后再次 运行 以减去折扣。所以我的问题是我怎样才能得到“SELECT SUM(od.discount)...”部分一次?

表的结构:

CREATE TABLE `orders` (
  `order_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `order_date` datetime NOT NULL,
  `shipping_address_id` int(11) NOT NULL,
  `shipping_price` float NOT NULL,
  `shipping_option_id` int(11) NOT NULL,
  `order_currency` varchar(5) CHARACTER SET utf8mb4 NOT NULL,
  `billing_address_id` int(11) NOT NULL,
  `status` enum('unpaid','paid','shipped') CHARACTER SET utf8mb4 NOT NULL,
  `admin_id` int(11) NOT NULL,
  `descr` text CHARACTER SET utf8mb4 NOT NULL,
  `payment_type` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
  `invoice_url` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
  `amount_paid` double NOT NULL,
  `stripe_src_id` varchar(50) NOT NULL,
  `ipn_message` text NOT NULL,
  `stripe_client_secret` varchar(255) NOT NULL,
  `order_total` double NOT NULL,
  `paid_via` enum('paypal','stripe','bancontact') NOT NULL,
  `order_notes` text CHARACTER SET utf8mb4 NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

--
-- Table structure for table `order_discounts`
--

CREATE TABLE `order_discounts` (
  `order_id` int(11) NOT NULL,
  `discount_id` int(11) NOT NULL,
  `discount` float NOT NULL,
  `currency` varchar(5) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;

-- --------------------------------------------------------

--
-- Table structure for table `order_products`
--

CREATE TABLE `order_products` (
  `op_id` int(11) NOT NULL,
  `order_id` int(11) NOT NULL,
  `product_id` int(11) NOT NULL,
  `amount` int(7) NOT NULL,
  `price` double NOT NULL,
  `currency` varchar(5) CHARACTER SET utf8mb4 NOT NULL,
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

--
-- Table structure for table `shipping_addresses`
--

CREATE TABLE `shipping_addresses` (
  `shipping_address_id` int(11) NOT NULL,
  `shipping_name` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

order_products order_discounts 中的 似乎每个 order_id 都有几行。如果是这样,我建议在子查询中聚合:

select 
    o.order_id, 
    sa.shipping_name as user,
    round(op.value - coalesce(od.value, 0), 2) order_total
from orders o
inner join (
    select order_id, sum(price * amount) value
    from order_products op
    group by order_id
) op on op.order_id = o.order_id
left join (
    select order_id, sum(discount) value
    from order_discounts 
    group by order_id
) od on od.order_id = o.order_id
left join shipping_addresses sa 
    on o.shipping_address_id = sa.shipping_address_id 
order by o.order_date desc, o.user_id desc

您还可以使用子查询:

select
    o.order_id,
    sa.shipping_name as user,
    round(
        (
            select sum(op.price * op.amount) 
            from order_products op 
            where op.order_id = o.order_id
        ) 
        - (
            select coalesce(sum(od.discount), 0)
            from order_discounts od
            where od.order_id = o.order_id
        ),
        2
    ) order_total
from orders o
left join shipping_addresses sa 
    on o.shipping_address_id = sa.shipping_address_id 
order by o.order_date desc, o.user_id desc