如何使用MySQL从属于查询本身一部分的表中进行“选择”?

如何使用MySQL从属于查询本身一部分的表中进行“选择”?,mysql,select,count,Mysql,Select,Count,例如,如果我有多个具有相同架构的表: CREATE TABLE `tbl01` ( `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `name` TINYTEXT, `data` INT ); CREATE TABLE `tbl02` ( `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `name` TINYTEXT, `data` INT ); CREATE TABLE `tbl

例如,如果我有多个具有相同架构的表:

CREATE TABLE `tbl01`
(
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `name` TINYTEXT,
  `data` INT
);

CREATE TABLE `tbl02`
(
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `name` TINYTEXT,
  `data` INT
);

CREATE TABLE `tbl03`
(
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `name` TINYTEXT,
  `data` INT
);

-- etc. ------------------

INSERT INTO `tbl01` (`name`, `data`) VALUES
('row 1', 1),
('row 2', 1),
('row 3', 3);

INSERT INTO `tbl02` (`name`, `data`) VALUES
('cube', 1),
('circle', 0);

INSERT INTO `tbl03` (`name`, `data`) VALUES
('one', 1);
然后是一个表,其中一列包含所有其他表的名称:

CREATE TABLE `AllTbls`
(
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `tblnm` VARCHAR(64) NOT NULL UNIQUE,
  `desc` TINYTEXT,
  `flgs` BIGINT UNSIGNED
);

INSERT INTO `AllTbls` (`tblnm`, `desc`, `flgs`) VALUES
('tbl01', 'Table 1', 0),
('tbl02', 'Table two', 1),
('tbl03', '3rd table', 0);
因此,如果我想编写一个查询来检索所有TBL的内容,并在一列中包含每个对应表中的行数,我认为以下方法可以做到:

SELECT *, `tblnm` as TblName, (SELECT COUNT(*) FROM TblName) as cntRws 
  FROM `AllTbls` ORDER BY `id` ASC LIMIT 0,30;
但这会返回一个错误:

1146-表“database.TblName”不存在

我知道我可以使用编程语言中的一个循环在多个查询中实现这一点,但是有可能在一个查询中实现吗


另外,我正在使用MySQL v.5.7.28,简单的答案是:你不能

表名不应该像变量一样用来保存数据。你应该有一张桌子:

tblContractCounts
Client, ContractCount
-------------------
IBM, 1
Microsoft, 3
Google, 2
不是三张表:

tblIBMContractCounts
ContractCount
1

tblMicrosoftContractCounts
ContractCount
3

tblGoogleContractCounts
ContractCount
2
如果表的数量已知且固定,您可能可以通过创建一个视图来修复问题,该视图将所有表重新合并在一起,或者开始一个操作,将所有表放在一个表中,并使用单独的视图命名为旧名称,以便在您可以更改它们之前,所有表都能正常工作。如果一直添加新表,这是数据建模中的一个缺陷,需要纠正。在这种情况下,您必须使用编程语言前端或存储过程来构建单个查询:

//pseudo code
strSql = ""
for each row in dbquery("Select name from alltbls")
  strSql += "select '" + row.name + "' as tbl, count(*) as ct from " + row.name + " union all "
next row
strSql += "select 'dummy', 0"

result = dbquery(strSql)
这样做不一定非得由前端完成——您也可以在mysql中完成,并利用动态sql/EXECUTE。请参阅如何使用上述逻辑连接字符串,以便该字符串包含sql查询,然后执行查询。信息模式将为您提供获取所有当前表名列表所需的信息

但你所做的一切都是围绕着你的数据建模被破坏这一事实而工作;我建议改为解决这个问题

ps:INFORMATION_SCHEMA对带有名称的表有粗略的计数,这可能足以满足您在这种特殊情况下的需要

select table_name, table_rows from infornation_schema.tables where table_name like ...

我使用以下存储过程设法解决了这个问题

-- DROP PROCEDURE sp_Count_Rows;
Delimiter $$
CREATE PROCEDURE sp_Count_Rows() 
BEGIN
DECLARE table_name TEXT DEFAULT "";
DECLARE finished INTEGER DEFAULT 0;
DECLARE table_cursor 
CURSOR FOR 
    SELECT tblnm FROM alltbls;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;

OPEN table_cursor;
DROP TABLE IF EXISTS RowsCount;
CREATE TABLE IF NOT EXISTS RowsCount(Tlbnm text, ctnRws int);

table_loop: LOOP

    FETCH table_cursor INTO table_name;

    IF finished = 1 THEN 
        LEAVE table_loop;
    END IF;

    SET @s = CONCAT("insert into RowsCount select '", table_name ,"', count(*) as cntRws from ", table_name);
    PREPARE stmt1 FROM @s; 
    EXECUTE stmt1; 
    DEALLOCATE PREPARE stmt1; 

END LOOP table_loop;
CLOSE table_cursor;

SELECT * FROM RowsCount;
DROP TABLE RowsCount;
END
$$
然后当你调用程序时

CALL sp_Count_Rows();

新表可以在任何时候由您无法控制的外部进程创建吗?@CaiusJard是的,它们可以在任何时候添加。没有动态SQL,您无法做到这一点。@TimBiegeleisen和动态SQL是什么?当我用编程语言编写它时,我不认为你可以使用/插入一个选定的字段作为from参数。也许如果你探索信息模式的上层查询?谢谢你的解释。谢谢。我得复习一下。不幸的是,我的MySQL版本只有5.7.28。是什么使它依赖于v.8?据我所知,没有什么特别的,但这是为了防止您不得不修改代码,或者数据库管理器给出了一些警告/问题。