Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 从一个表中选择行,并根据另一个表中的行调整值_Mysql - Fatal编程技术网

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

Mysql 从一个表中选择行,并根据另一个表中的行调整值,mysql,Mysql,我有一个带有ID和相应价格的小部件表。我还有一张折扣表。每个小部件可以有多个折扣,每个都是固定金额或百分比折扣。复合折扣必须按照其头寸指定的顺序应用 widgets id | price ---------- 1 | 10.50 2 | 2.25 3 | 15.75 discounts id | widgetId | fixedDiscount | percentageDiscount | position 1 | 1 | 0.35 |

我有一个带有ID和相应价格的小部件表。我还有一张折扣表。每个小部件可以有多个折扣,每个都是固定金额或百分比折扣。复合折扣必须按照其头寸指定的顺序应用

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
我是否可以创建一个查询/程序,在应用所有折扣后选择每个小部件及其最终价格

使用上述示例数据:

- 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)
我知道的唯一方法是将折扣表连接到widgets表,然后在获得所有数据后用PHP计算最终价格。然而,我的数据是这个假设例子的一个更复杂的版本。对于我试图生成的报告,可能会有数百个widget,其中许多widget的折扣超过了一小部分

上面的示例数据可以这样创建:

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');

我们决定解决这个问题的方法是通过一个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;
我们可以选择以下数据以检索每个小部件的折扣价格:

SELECT 
    id,
    price,
    widgetPrice(id) AS discountedPrice
FROM 
widgets;
这给了我们:

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

我们决定解决这个问题的方法是通过一个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;
我们可以选择以下数据以检索每个小部件的折扣价格:

SELECT 
    id,
    price,
    widgetPrice(id) AS discountedPrice
FROM 
widgets;
这给了我们:

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

@草莓,希望更新的版本能提供你想要的。感谢您的反馈。@草莓,希望更新后的版本能满足您的需求。谢谢你的反馈。