为了减小其中一个表的大小(目前超过 400 万行),我创建了一个“存档”表,该表只能由某些用户访问。
归档表是主表的副本,只不过它包含很少被访问的旧行。
但是,有时我需要查询两个表:
SELECT
t1.*,
t6.*
FROM (
SELECT
COUNT(DISTINCT up.lesson_id) AS assessment_count,
MIN(up.date) AS first_date,
MAX(up.date) AS last_date
FROM
cdu_user_progress up
WHERE
(up.game_id = '0') AND
(up.uid = '150') AND
(up.lesson_id IN ('65', '1112', '66', '67', '68', '69', '1114', '70', '71', '72', '73', '74', '75', '1113', '77', '424', '423', '1115', '93', '94', '95', '420', '421', '422', '96', '97', '98', '99', '100', '101', '1015', '102', '415', '104', '106', '105', '107', '108', '1016', '109', '110', '160', '111', '113', '112', '738', '739', '1050', '1051', '116', '117', '118', '119', '120', '121', '1017', '123', '124', '125', '130', '1018', '131', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '267', '268', '269', '270', '271', '272', '273', '274', '1019', '278', '775', '279', '280', '281', '282', '283', '284', '285', '286', '1161', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', '297', '298', '299', '300', '301', '318', '319', '302', '303', '304', '305', '306', '307', '308', '309', '337', '338', '339', '340', '341', '342', '343', '344', '345', '346', '1054', '347', '348', '349', '350', '351', '352', '353', '354', '355', '356', '377', '378', '379', '380', '479', '480', '481', '482', '431', '432', '433', '434', '435', '436', '437', '438', '439', '440', '441', '442', '443', '444', '445', '446', '448', '447', '449', '450', '451', '452', '453', '454', '456', '455', '457', '458', '459', '460', '461', '462', '463', '464', '465', '466', '467', '468', '469', '470', '471', '472', '473', '474', '475', '476', '477', '478', '1090')) AND
(up.score > '-1')
) t1
INNER JOIN (
SELECT
AVG(c1.score) AS avg_first_scores,
SUM(c1.score) AS sum_first_scores
FROM
cdu_user_progress c1
LEFT OUTER JOIN cdu_user_progress c2 ON c1.uid = c2.uid AND c1.lesson_id = c2.lesson_id AND c1.game_id = c2.game_id AND c1.level = c2.level AND c1.date > c2.date AND c2.score > -1
WHERE
(c1.game_id = '0') AND
(c1.uid = '150') AND
(c1.lesson_id IN ('65', '1112', '66', '67', '68', '69', '1114', '70', '71', '72', '73', '74', '75', '1113', '77', '424', '423', '1115', '93', '94', '95', '420', '421', '422', '96', '97', '98', '99', '100', '101', '1015', '102', '415', '104', '106', '105', '107', '108', '1016', '109', '110', '160', '111', '113', '112', '738', '739', '1050', '1051', '116', '117', '118', '119', '120', '121', '1017', '123', '124', '125', '130', '1018', '131', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '267', '268', '269', '270', '271', '272', '273', '274', '1019', '278', '775', '279', '280', '281', '282', '283', '284', '285', '286', '1161', '287', '288', '289', '290', '291', '292', '293', '294', '295', '296', '297', '298', '299', '300', '301', '318', '319', '302', '303', '304', '305', '306', '307', '308', '309', '337', '338', '339', '340', '341', '342', '343', '344', '345', '346', '1054', '347', '348', '349', '350', '351', '352', '353', '354', '355', '356', '377', '378', '379', '380', '479', '480', '481', '482', '431', '432', '433', '434', '435', '436', '437', '438', '439', '440', '441', '442', '443', '444', '445', '446', '448', '447', '449', '450', '451', '452', '453', '454', '456', '455', '457', '458', '459', '460', '461', '462', '463', '464', '465', '466', '467', '468', '469', '470', '471', '472', '473', '474', '475', '476', '477', '478', '1090')) AND
(c1.score > '-1') AND
(c2.date IS '')
) t6
我已经想到的解决方案 - 将 SELECT cdu_user_progress
替换为嵌套查询:
SELECT * FROM cdu_user_progress UNION SELECT * FROM cdu_user_progress_archive
但这会在内存中创建一个巨大的临时表。
我尝试了每个查询的 UNION(上面的嵌套查询),但这会导致返回多行,而过去它只返回单行。
SELECT
...
FROM (
SELECT
...
FROM
cdu_user_progress up
WHERE
...
UNION SELECT
...
FROM
cdu_user_progress_archive up
WHERE
...
) t1
INNER JOIN (
SELECT
...
FROM
cdu_user_progress c1
LEFT OUTER JOIN cdu_user_progress c2 ON c1.uid = c2.uid AND c1.lesson_id = c2.lesson_id AND c1.game_id = c2.game_id AND c1.level = c2.level AND c1.date > c2.date AND c2.score > -1
WHERE
...
UNION SELECT
...
FROM
cdu_user_progress_archive c1
LEFT OUTER JOIN cdu_user_progress_archive c2 ON c1.uid = c2.uid AND c1.lesson_id = c2.lesson_id AND c1.game_id = c2.game_id AND c1.level = c2.level AND c1.date > c2.date AND c2.score > -1
WHERE
...
) t6
还有其他想法吗???
谢谢!
最佳答案
这些 suq 查询包含聚合。
因此,一个简单的解决方案就是违反 DRY 原则(不要重复自己)。
IE。复制并粘贴这些查询,更改为存档表并将它们合并。
但是 Lesson_id 的列表相当长。
可能最好将它们放入临时表中,以便可以重用。
SELECT t1.*, t6.*
FROM (
SELECT 'current' as Src,
COUNT(DISTINCT up.lesson_id) AS assessment_count,
MIN(up.date) AS first_date,
MAX(up.date) AS last_date
FROM cdu_user_progress up
INNER JOIN temp_lessonid_list lst
ON lst.lesson_id = up.lesson_id
WHERE up.game_id = 0
AND up.uid = 150
AND up.score > -1
UNION ALL
SELECT 'archive' as Src,
COUNT(DISTINCT up.lesson_id) AS assessment_count,
MIN(up.date) AS first_date,
MAX(up.date) AS last_date
FROM cdu_user_progress_archive up
INNER JOIN temp_lessonid_list lst
ON lst.lesson_id = up.lesson_id
WHERE up.game_id = 0
AND up.uid = 150
AND up.score > -1
) t1
INNER JOIN
(
SELECT 'current' as Src,
AVG(c1.score) AS avg_first_scores,
SUM(c1.score) AS sum_first_scores
FROM cdu_user_progress c1
INNER JOIN temp_lessonid_list lst
ON lst.lesson_id = c1.lesson_id
LEFT JOIN cdu_user_progress c2
ON (c1.uid = c2.uid AND c1.lesson_id = c2.lesson_id AND c1.game_id = c2.game_id AND c1.level = c2.level AND c1.date > c2.date AND c2.score > -1)
WHERE c1.game_id = 0
AND c1.uid = 150
AND c1.score > -1
AND c2.date IS ''
UNION ALL
SELECT 'archive' as Src,
AVG(c1.score) AS avg_first_scores,
SUM(c1.score) AS sum_first_scores
FROM cdu_user_progress_archive c1
INNER JOIN temp_lessonid_list lst
ON lst.lesson_id = c1.lesson_id
LEFT JOIN cdu_user_progress_archive c2
ON (c1.uid = c2.uid AND c1.lesson_id = c2.lesson_id AND c1.game_id = c2.game_id AND c1.level = c2.level AND c1.date > c2.date AND c2.score > -1)
WHERE c1.game_id = 0
AND c1.uid = 150
AND c1.score > -1
AND c2.date IS ''
) t6 ON t6.Src = t1.Src;
您还可以研究表分区。
关于mysql - 立即从表 AND 'archive' 表中选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58919440/