我尝试使用临时表作为SELECT语句的中间结果持有者。问题是虽然我无法在其他查询语句中多次访问临时表,我希望这可能会使临时表无效。
MySql中是否有替代临时表,允许我提取我的SQL语句。
我无法使用存储过程(无法从公司使用的Web框架版本访问它们)而且我不想使用游标。
编辑:
我的代码看起来有点像这样:
创建临时表:
CREATE TEMPORARY TABLE dates_with_entries (
seq INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
datum VARCHAR(32)
);
INSERT INTO dates_with_entries (datum) SELECT datum AS Datum from project_times
WHERE user_id = 20 GROUP BY datum ORDER BY datum desc LIMIT 13;
然后我使用临时表的代码看起来有点像这样(我把它简化为我遇到的问题......)
SELECT
...
FROM (SELECT entrie_date AS datum FROM dates_with_entries ) AS sub_result
INNER JOIN project_times
ON sub_result.datum = project_times.datum AND project_times.user_id = 20
LEFT JOIN works AS w ON project_times.work_id = w.id
LEFT JOIN sub_projects AS sp ON sp.id = w.sub_project_id
LEFT JOIN projects AS p ON p.id = sp.project_id
GROUP BY datum
UNION(
SELECT
..
FROM (SELECT entrie_date AS datum FROM dates_with_entries ) AS sub_result
INNER JOIN project_times AS pt ON pt.datum = sub_result.datum
INNER JOIN works AS w on w.id = pt.work_id
INNER JOIN sub_projects AS sp on w.sub_project_id = sp.id
INNER JOIN projects AS p ON sp.project_id = p.id
WHERE pt.user_id = 20
);
这些数字稍后将被ruby替换,这仅用于测试SQL语句。
答案 0 :(得分:4)
解决这个问题的一种方法是简单地创建一个“真实”表,而不是临时表。
临时表提供的优势:
如果#1对您至关重要,那么您可能需要坚持使用临时表。否则,如果一次只运行此程序的一个实例,或者您动态创建表名以使其唯一,我建议您为此表选择一个适当的唯一名称并将其创建为“真实”表,然后你完成后放弃它。
答案 1 :(得分:2)
已知错误(功能) - 阅读http://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html
以下是我解决问题的方法......
drop table if exists employees;
create table employees
(
emp_id smallint unsigned not null auto_increment primary key,
name varchar(255) not null,
boss_id smallint unsigned null,
key (boss_id)
)
engine = innodb;
insert into employees (name, boss_id) values
('f00',null),
('ali later',1),
('megan fox',1),
('jessica alba',3),
('eva longoria',3),
('keira knightley',5),
('liv tyler',6),
('sophie marceau',6);
drop procedure if exists employees_hier;
delimiter #
create procedure employees_hier
(
in p_emp_id smallint unsigned
)
begin
declare v_done tinyint unsigned default(0);
declare v_dpth smallint unsigned default(0);
create temporary table hier(
boss_id smallint unsigned,
emp_id smallint unsigned,
depth smallint unsigned
)engine = memory;
insert into hier select boss_id, emp_id, v_dpth from employees where emp_id = p_emp_id;
/* http://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html */
create temporary table emps engine=memory select * from hier;
while not v_done do
if exists( select 1 from employees e inner join hier on e.boss_id = hier.emp_id and hier.depth = v_dpth) then
insert into hier select e.boss_id, e.emp_id, v_dpth + 1
from employees e inner join emps on e.boss_id = emps.emp_id and emps.depth = v_dpth;
set v_dpth = v_dpth + 1;
truncate table emps;
insert into emps select * from hier where depth = v_dpth;
else
set v_done = 1;
end if;
end while;
select
e.emp_id,
e.name as emp_name,
p.emp_id as boss_emp_id,
p.name as boss_name,
hier.depth
from
hier
inner join employees e on hier.emp_id = e.emp_id
left outer join employees p on hier.boss_id = p.emp_id;
drop temporary table if exists hier;
drop temporary table if exists emps;
end #
delimiter ;
-- call this sproc from your php
call employees_hier(1);
答案 2 :(得分:0)
对于这个问题,只读取临时表,我创建第二个临时表作为第一个临时表的副本,然后在查询中使用它:
CREATE TEMPORARY TABLE t2 as (SELECT * FROM dates_with_entries);
然后
SELECT
...
FROM (SELECT entrie_date AS datum FROM dates_with_entries ) AS sub_result
INNER JOIN project_times
ON sub_result.datum = project_times.datum AND project_times.user_id = 20
LEFT JOIN works AS w ON project_times.work_id = w.id
LEFT JOIN sub_projects AS sp ON sp.id = w.sub_project_id
LEFT JOIN projects AS p ON p.id = sp.project_id
GROUP BY datum
UNION(
SELECT
..
FROM (SELECT entrie_date AS datum FROM t2) AS sub_result
INNER JOIN project_times AS pt ON pt.datum = sub_result.datum
INNER JOIN works AS w on w.id = pt.work_id
INNER JOIN sub_projects AS sp on w.sub_project_id = sp.id
INNER JOIN projects AS p ON sp.project_id = p.id
WHERE pt.user_id = 20
);
答案 3 :(得分:0)
我为这个问题尝试了“ WITH”,但是显然我的服务器上的MySQL还不支持它。我遇到了似乎可行的解决方案。它使用“ CREATE VIEW”在MySQL中复制“ WITH”
http://guilhembichot.blogspot.com/2013/11/with-recursive-and-mysql.html