2014-10-30 2 views
1

Я хочу, чтобы найти оптимальный способ запустить этот запрос, здесь детали, позволяет сказать следующее мои таблицы с их данными:Лучший и оптимальный способ объединения максимальное значение из другой таблицы

-- User Table 
DROP TABLE IF EXISTS `users`; 
CREATE TABLE `users` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(30) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM; 

-- Entries 
INSERT INTO `users` VALUES (1,'user_a'); 
INSERT INTO `users` VALUES (2,'user_b'); 
INSERT INTO `users` VALUES (3,'user_c'); 

-- User Log Table 
DROP TABLE IF EXISTS `user_log`; 
CREATE TABLE `user_log` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `idrel` int(11) NOT NULL, 
    `event` varchar(20) NOT NULL, 
    `log` datetime NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `idrel` (`idrel`,`log`) 
) ENGINE=MyISAM; 

-- Entries 
INSERT INTO `user_log` VALUES (1,1,'log1','2014-01-01 13:00:00'); 
INSERT INTO `user_log` VALUES (2,1,'log2','2014-01-02 13:00:00'); 
INSERT INTO `user_log` VALUES (3,2,'log3','2014-01-03 13:00:00'); 
INSERT INTO `user_log` VALUES (4,2,'log4','2014-01-04 13:00:00'); 
INSERT INTO `user_log` VALUES (5,3,'log5','2014-01-05 13:00:00'); 
INSERT INTO `user_log` VALUES (6,3,'log6','2014-01-06 13:00:00'); 

И я хочу запросить пользователей, присоединяющихся к последнему зарегистрированному событию, я нашел два способа сделать это, но я не знаю, какой из них лучше (говорить о скорости, когда обе таблицы растут), или если есть другой способ, вот мои запросы :

-- Query 1 
SELECT 
    u.id, 
    u.name, 
    l2.event as last_record 
FROM 
    users AS u 
INNER JOIN 
    (
     SELECT 
      idrel, 
      MAX(id) as last_id 
     FROM user_log 
     GROUP BY 
      idrel 
    ) AS l1 
    ON (l1.idrel = u.id) 
INNER JOIN 
     user_log AS l2 
     ON (l2.id = l1.last_id); 

Который дает мне этот результат:

+----+--------+-------------+ 
| id | name | last_record | 
+----+--------+-------------+ 
| 1 | user_a | log2  | 
| 2 | user_b | log4  | 
| 3 | user_c | log6  | 
+----+--------+-------------+ 
3 rows in set (0.00 sec) 
-- Query 2 
SELECT 
    u.id, 
    u.name, 
    (
     SELECT event FROM user_log WHERE idrel = u.id ORDER BY log DESC LIMIT 1 
    ) AS last_record 
FROM 
    users AS u; 

И результат:

+----+--------+-------------+ 
| id | name | last_record | 
+----+--------+-------------+ 
| 1 | user_a | log2  | 
| 2 | user_b | log4  | 
| 3 | user_c | log6  | 
+----+--------+-------------+ 
3 rows in set (0.00 sec) 

Какой может быть лучшим способом? Есть ли другой лучший способ?

+1

'MAX (event)' дает вам отсортированную по алфавиту последнюю запись, не основанную на времени регистрации. Итак: нет. – Wrikken

+0

FWIW: 'SELECT u.id, u.name, (SELECT event FROM user_log WHERE idrel = u.id ORDER BY log DESC LIMIT 1) AS last_record ОТ пользователей AS u;' приближается к тому, что вы, вероятно, хотите. – Wrikken

+0

Действительно, я не знаю, о чем думал. –

ответ

1

Не делайте этого, вот лучший способ, во-первых, добавить поле для хранения в таблице пользователей последнего идентификатора любой новой записи журнала, а затем создать триггер, который обновляет это поле в каждом новом поле вставлен, затем (необязательно) создает представление для получения полной «таблицы» для запроса.

-- Add new field to save the modified id 
ALTER TABLE `users` ADD `last_mod_id` INT(11) NOT NULL, ADD INDEX (`last_mod_id`); 

-- Drop the trigger just in case it exists 
DROP TRIGGER IF EXISTS `update_last_id`; 

-- Create a trigger to save the last modified id each time a row is created 
DELIMITER ;; 
CREATE TRIGGER update_last_id 
    AFTER INSERT ON user_log 
    FOR EACH ROW 
    BEGIN 
     UPDATE `users` 
     SET `last_mod_id` = NEW.id 
     WHERE `id` = NEW.idrel; 
    END; 
;; 

-- Emtpy your table 
TRUNCATE `user_log`; 

-- Create all new registries 
INSERT INTO `user_log` VALUES (1,1,'log1','2014-01-01 13:00:00'); 
INSERT INTO `user_log` VALUES (2,1,'log2','2014-01-02 13:00:00'); 
INSERT INTO `user_log` VALUES (3,2,'log3','2014-01-03 13:00:00'); 
INSERT INTO `user_log` VALUES (4,2,'log4','2014-01-04 13:00:00'); 
INSERT INTO `user_log` VALUES (5,3,'log5','2014-01-05 13:00:00'); 
INSERT INTO `user_log` VALUES (6,3,'log6','2014-01-06 13:00:00'); 


-- Query 
SELECT 
    u.id, 
    u.name, 
    u.last_mod_id, 
    l.event, 
    l.log 
FROM 
    `users` as u 
INNER JOIN 
    `user_log` as l 
    ON (l.id = u.last_mod_id) 

-- Drop view if exists 
DROP VIEW IF EXISTS `users_log_view`; 

-- View 
CREATE VIEW `users_log_view` AS 
    SELECT 
     u.id, 
     u.name, 
     u.last_mod_id, 
     l.event, 
     l.log 
    FROM 
     `users` as u 
    INNER JOIN 
     `user_log` as l 
     ON (l.id = u.last_mod_id); 

-- Query 
SELECT * FROM `users_log_view` WHERE `id` = 1; 
+1

Денормализация, но с очень хорошей причиной, я в пользу этого решения масштабируемости. – Wrikken

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