2016-06-27 1 views
0

Как улучшить это представление mysql?Есть ли возможность избежать двух подзапросов, которые обращаются к одной и той же таблице?

Я думаю, что нет необходимости выполнять два подзапроса, которые с доступом как к одной и той же таблицы jc_donation_method с тем же WHERE CLAUSE = d.donation_method = m.donation_method, но разные SELECT CLAUSEL. Но я не знаю, как этого избежать.

donation_id является первичным ключом в jc_donation и внешним ключом jc_donation_method.

 
CREATE 
    OR REPLACE 
    ALGORITHM = MERGE 
    VIEW jc_donation_total AS 
SELECT 
    d.donation_method, 
    (SELECT 
     m.method_name 
    FROM 
     `jc_donation_method` m 
    WHERE 
     d.donation_method = m.donation_method 
    LIMIT 1) method_name, 
    CAST(SUM(d.donation_amount- 
    (SELECT 
     m.method_fee_nonrecurring 
    FROM 
     `jc_donation_method` m 
    WHERE 
     d.donation_method = m.donation_method 
    LIMIT 1) 
    - d.donation_amount*(
    (SELECT 
     m.method_fee_percent 
    FROM 
     `jc_donation_method` m 
    WHERE 
     d.donation_method = m.donation_method 
    LIMIT 1)) 
) as decimal(12,4)) donation_total 
FROM 
    `jc_donation` d 
LEFT JOIN 
    `jc_user` u 
ON 
    d.user_id = u.user_id 
GROUP BY 
    d.donation_method 
HAVING 
    COUNT(u.user_id) > 0 

В основном я хотел бы знать все общие пожертвования, которые сделаны с помощью активных пользователей в donation_method: сумма - Разовые сборы - процент сборов% (за одиночные пожертвования).

Предпосылка:

 
CREATE TABLE `jc_user` (
    `user_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`user_id`) USING BTREE 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='User credentials'; 

CREATE TABLE `jc_donation_method` (
    `donation_method` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, 
    `method_name` varchar(32) NOT NULL, 
    `method_fee_percent` decimal(6,4) NOT NULL DEFAULT 0.00, 
    `method_fee_nonrecurring` decimal(5,2) NOT NULL DEFAULT 0.00, 
    PRIMARY KEY (`donation_method`) USING BTREE, 
    UNIQUE KEY `method_name` (`method_name`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Donation methods and fees'; 

INSERT INTO 
    `jc_donation_method` (`donation_method`, `method_name`, 
    `method_fee_percent`, `method_fee_nonrecurring`) 
VALUES 
    (NULL, 'Transfer',0.000,0.00), 
    (NULL, 'PayPal',0.0190,0.35); 

CREATE TABLE `jc_donation` (
    `donation_id` int(10) NOT NULL AUTO_INCREMENT, 
    `user_id` int(10) UNSIGNED NOT NULL, 
    `donation_method` int(10) UNSIGNED NOT NULL DEFAULT '1', 
    `donation_amount` decimal(12,4) NOT NULL, 
    PRIMARY KEY (`donation_id`) USING BTREE, 
    FOREIGN KEY (user_id) REFERENCES jc_user(user_id), 
    FOREIGN KEY (donation_method) REFERENCES jc_donation_method(donation_method) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Donations'; 
+0

Обычно, прямо сейчас я бы говорить о 'ВНУТРЕННЕЙ JOIN', но дегтя в этой бочке меда, кажется,' 1' LIMIT положение в каждой из вложенных запросов. ## Сказав *, что * моя личная нижняя строка (чтобы процитировать Seuss * * Green Eggs and Ham *): «Мне не нравится этот запах этого взгляда, Sam-I-Am». Я думаю, что логика * должна * использовать 'INNER JOIN', но это обязательно означает, что все пользователи этого представления в любом месте приложения должны быть готовы видеть больше, чем одну строку в результате. –

+0

Хорошо, есть таблица, содержащая все пожертвования 'jc_donations' by' donation_id'. В другой таблице 'jc_user' хранятся все пользователи. Каждый пользователь может сделать несколько пожертвований. Каждое пожертвование может основываться на разных методах ('donation_method) в' jc_donation_method' как банковский перевод или paypal. Большинство платформ взимают плату. Как единовременные сборы за каждую передачу или оплату за перцентацию. Некоторые из них оба (Paypal). Это представление должно представлять общий доход после сборов за метод donation_method. – EaglePsyX

+0

Внутреннее соединение было бы правильным методом, и вам кажется, что вы хотите, чтобы внутреннее соединение было подчинено запросу, которое агрегируется до уровня, который вам нужен, чтобы пройти только одну запись. – Jeff

ответ

1

Как я уже говорил в своем первоначальном комментарии, я не уверен, почему пользователь имеет отношение, но это должно быть самым простым запрос, чтобы получить то, что вы хотите:

SELECT m.donation_method, m.method_name 
    , CAST(
     d.donation_amount 
     - m.method_fee_nonrecurring 
     - (d.donation_amount * m.method_fee_percent) 
    AS DECIMAL(12, 4)) donation_total 
FROM jc_donation_method AS m 
INNER JOIN jc_donation AS d 
ON m.donation_method = d.donation_method 
GROUP BY m.donation_method 
; 

. Следующая версия должна учитываться пользователями, такими как ваш оригинал.

SELECT m.donation_method, m.method_name 
    , CAST(
     d.donation_amount 
     - m.method_fee_nonrecurring 
     - (d.donation_amount * m.method_fee_percent) 
    AS DECIMAL(12, 4)) donation_total 
FROM jc_donation_method AS m 
INNER JOIN jc_donation AS d 
INNER JOIN jc_user AS u ON d.user_id = u.user_id 
ON m.donation_method = d.donation_method 
GROUP BY m.donation_method 
; 
+0

Большое спасибо! Вы совершенно правы! Я оставил пользователя в каком-то случае, когда я должен не доверять платежу пользователя, но вместо этого я использую 'donation_canceled' в таблице пожертвований =) – EaglePsyX

Смежные вопросы