简体   繁体   English

从一个表中选择行并根据另一表中的行调整值

[英]Select rows from one table and adjust the values based on rows in another table

I have a table of widgets with an ID and corresponding price.我有一个带有 ID 和相应价格的小部件表。 I also have a table of discounts.我也有一张折扣表。 There can be multiple discounts per widget, each being either a fixed amount or percentage reduction.每个小部件可以有多个折扣,每个折扣都是固定金额或百分比减少。 Compound discounts must be applied in the order specified by their position.复合折扣必须按其位置指定的顺序应用。

widgets

id | price
----------
1  | 10.50
2  | 2.25
3  | 15.75

discounts

id | widgetId | fixedDiscount | percentageDiscount | position
1  | 1        | 0.35          |                    | 1
2  | 1        |               | 25                 | 2
3  | 3        |               | 10                 | 1

Could I create a query/procedure which would select each widget and its final price, after all discounts had been applied?在应用所有折扣后,我可以创建一个查询/程序来选择每个小部件及其最终价格吗?

With the sample data above:使用上面的示例数据:

- Widget 1 should have a 0.35 reduction, then further reduced by 25%. (2 discounts)
- Widget 2 should be unchanged at the original 2.25 (no discount)
- Widget 3 should have a 10% reduction (1 discount)

The only way I am aware of is to join the discounts table to the widgets table and then calculate the final price in PHP once I have all the data.我知道的唯一方法是将折扣表加入小部件表,然后在获得所有数据后用 PHP 计算最终价格。 However, my data is a much more complicated version of this hypothetical example.但是,我的数据是这个假设示例的复杂得多的版本。 There are likely to be hundreds of widgets with many having more than a handful of discounts for the report I am trying to generate.可能有数百个小部件,其中许多小部件对我试图生成的报告有很多折扣。

Sample data above can be created like so:可以像这样创建上面的示例数据:

CREATE TABLE `widgets` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `price` DECIMAL(5,2) NOT NULL,
  PRIMARY KEY (`id`));

CREATE TABLE `discounts` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `widgetId` INT NOT NULL,
  `fixedDiscount` DECIMAL(5,2) NULL,
  `percentageDiscount` DECIMAL(4,2) NULL,
  `position` TINYINT NOT NULL,
  PRIMARY KEY (`id`),
  INDEX `fk_widgets_discounts_idx` (`widgetId` ASC),
  CONSTRAINT `fk_widgets_discounts`
    FOREIGN KEY (`widgetId`)
    REFERENCES `widgets` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);

INSERT INTO 
  `widgets` (`id`, `price`) 
VALUES 
  ('1', '10.50'),
  ('2', '2.25'),
  ('3', '15.75');

INSERT INTO 
  `discounts` (`id`, `widgetId`, `fixedDiscount`, `percentageDiscount`, `position`) 
VALUES
  ('1', '1', '0.35', null , '1'),
  ('2', '1', null, '25', '2'),
  ('3', '3', null, '10', '1');

The way we decided to solve this problem was by means of a MySQL function which returns the discounted price of a widget from its id.我们决定解决这个问题的方法是通过一个 MySQL 函数,它从一个小部件的 id 返回一个小部件的折扣价格。

DELIMITER $$
CREATE FUNCTION `widgetPrice`(p_widgetId INT) RETURNS decimal(5,2)
BEGIN

    DECLARE v_maxPos INT;
    DECLARE v_startPos INT;
    DECLARE v_newPrice DECIMAL(5,2);
    DECLARE v_fixedDiscount DECIMAL(5,2);
    DECLARE v_percentageDiscount DECIMAL(4,2);
    DECLARE v_discount DECIMAL (5,2);

    SELECT MAX(position) FROM discounts WHERE widgetId = p_widgetId INTO v_maxPos;
    SELECT price FROM widgets WHERE id = p_widgetId INTO v_newPrice;
    SET v_startPos = 1;

    WHILE v_maxPos > 0 DO
        SET v_fixedDiscount = 0;
        SET v_percentageDiscount = 0;
        SET v_discount = 0;

        SELECT fixedDiscount, percentageDiscount FROM discounts WHERE widgetId = p_widgetId AND position = v_startPos INTO v_fixedDiscount, v_percentageDiscount;

        IF ( v_fixedDiscount IS NOT NULL ) THEN
            SET v_discount = v_fixedDiscount;
        ELSEIF ( v_percentageDiscount IS NOT NULL ) THEN
             SET v_discount = v_newPrice * v_percentageDiscount / 100;
        END IF;

        SET v_newPrice = v_newPrice - v_discount;
        SET v_maxPos = v_maxPos - 1;
        SET v_startPos = v_startPos + 1;
    END WHILE;

    RETURN v_newPrice;
END$$
DELIMITER;

We can SELECT data as follows to retrieve each widget with its discounted price:我们可以按如下方式选择数据来检索每个小部件的折扣价:

SELECT 
    id,
    price,
    widgetPrice(id) AS discountedPrice
FROM 
widgets;

Which gives us:这给了我们:

id | price  |  discountedPrice
------------------------------
1  | 10.50  |  7.61
2  | 2.25   |  2.25
3  | 15.75  |  14.17

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 MySql - 如何根据在另一个表中加入的多个值从一个表中 select 行 - MySql - how to select rows from one table based on multiple values joined in another table 如何根据一个表中的值选择另一个表中的行并对其排序? - How can I select and order rows from one table based on values contained in another? MySQL根据另一个表的行选择一个表中的不同行 - Mysql select distinct rows in one table based on rows of another Select 来自一个表的行,当存在时使用另一个表中的值 - Select rows from one table, using values from another table when present 如何从一个表中选择行作为CSV并根据键插入另一个表? - How do I select rows from one table as CSV and insert into another table based on a key? MySQL项目设计-根据另一个选择查询中的行有条件地从一个表中选择 - MySQL project design - conditionally select from one table based on rows from another select query 如果其中一个与另一个表匹配,则从表中选择行 - Select rows from a table if one of them matches with another table 从表中选择只连接另一个表的一行的行 - SELECT rows from a table joining only one row of another table 从一个表中选择行,其中另一表中的多行已确定值 - Select row from one table where multiple rows in another table have determined values 如何使用基于公共参数的另一个表中的值更新一个表中的行 - How to update rows of one table with values from another table based on common parameter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM