Как `ВЫБРАТЬ ИЗ`` таблицу, которая является частью самого запроса, используя MySQL? - PullRequest
0 голосов
/ 04 апреля 2020

Скажем, если у меня несколько таблиц с одинаковой схемой:

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);

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

SELECT *, `tblnm` as TblName, (SELECT COUNT(*) FROM TblName) as cntRws 
  FROM `AllTbls` ORDER BY `id` ASC LIMIT 0,30;

Но это возвращает ошибку:

# 1146 - Таблица 'database.TblName' не существует

Я знаю, что могу сделать это в нескольких запросах (используя al oop на языке программирования), но возможно ли сделать это одним запросом?

PS. Я пользуюсь MySQL v.5.7.28

Ответы [ 2 ]

1 голос
/ 04 апреля 2020

Простой ответ: «Вы не можете»

Имена таблиц не должны использоваться как переменные для хранения данных таким образом. То, что вы должны иметь, это одна таблица:

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 и используйте динамику c sql / EXECUTE. Смотрите ЭТО ОТВЕТ , как мы можем объединить строку, используя logi c, как указано выше, чтобы строка содержала запрос sql, а затем выполнить запрос. Информационная схема предоставит вам информацию, необходимую для получения списка всех текущих имен таблиц

Но все, что вы делаете, - это работаете над тем, что ваше моделирование данных не работает; Я рекомендую исправить это вместо

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

select table_name, table_rows from infornation_schema.tables where table_name like ...
0 голосов
/ 04 апреля 2020

Мне удалось решить проблему, используя следующую хранимую процедуру.

-- 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();

Вы получите этот результат

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...