Here is the nested query i am using:
insert into ( select dbtable from profiles where ( email = 'blah#test.com' ) ) values ( null, null, 'blah#test.com', 'testing' )
the tablename will be fetched by the SELECT query for the INSERT query to run but i am getting this #1064 error.
I get another error of "#1103 - Incorrect table name" if i use back-ticks like this:
insert into `( select dbtable from profiles where ( email = 'blah#test.com' ) )` values ( null, null, 'blah#test.com', 'testing' )
I tried and searched for this but still i am stuck here. Can anybody help?
Sorry if this is an easy question as i am a newbie in this.
select dbtable from profiles where ( email = 'blah#test.com' ) into #tableName;
set #queryy = CONCAT(CONCAT('INSERT INTO ', #tableName), ' values ( null, null, \'blah#test.com\', \'testing\' )');
prepare myQuery from #queryy;
execute myQuery;
deallocate prepare myQuery;
I think it should help you solve your problem.
Related
I have the following Table with the following Data inside:
id
text
lanuage
1
deutscher text
german
2
english text
english
What I want is to get the Result in the following Format:
german="deutscher text"
english="english text"
This menas, it should be not:
text="deutscher text"
text="english text"
The Key/Column Name text should be the data from language
I tried the following Query but its not working:
SELECT text as (SELECT language FROM `table` where id = 1) FROM `table` where id = 1;
(SELECT language FROM table where id = 1) will return "german" so the Query should be:
"SELECT text as german FROM table where id = 1;" but this is not working.
Is there a way to do this in one Query?
Cheers, Thomas
One option you can use is PREPARED STATEMENT:
SET #sql := NULL;
SELECT GROUP_CONCAT(
CONCAT('MAX(CASE WHEN language="',language,'" THEN text END) AS "',language,'"'))
INTO #sql
FROM mytable;
SELECT CONCAT('SELECT ',#sql,' FROM mytable;') INTO #sql;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
First step is dynamically assigning columns required to the #sql variable. Then, concatenating the previously assigned #sql variable with the rest of the final SELECT query, then re-assign it to the #sql variable. The query will end up with:
SELECT MAX(CASE WHEN language="german" THEN text END) AS "german",
MAX(CASE WHEN language="english" THEN text END) AS "english"
FROM mytable;
Lastly, we prepare, execute then deallocate the statement assigned in the #sql variable and you'll get your expected result.
Demo fiddle
You'll have to alter your table schema a bit; Added a ref to group the languages to use
CREATE TABLE IF NOT EXISTS `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ref` int(11) DEFAULT 0,
`text` varchar(50) DEFAULT NULL,
`language` varchar(50) DEFAULT NULL,
KEY `Index 1` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb3;
Then the SQL
SELECT T.text AS english, T2.text AS german
FROM test T
INNER JOIN test T2 ON T.ref = T2.ref AND T2.`language` = 'german'
WHERE
T.ref = 1 AND
T.language = 'english'
The dummy data
INSERT INTO `test` (`id`, `ref`, `text`, `language`) VALUES
(1, 1, 'deutscher text', 'german'),
(2, 1, 'english text', 'english');
Say, if I have multiple tables that have the same schema:
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);
and then one table that contains names of all other tables in one of its columns:
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);
So if I want to write a query to retrieve contents of AllTbls and also in one column to include count of rows in each of corresponding tables, I thought the following would be the way to do it:
SELECT *, `tblnm` as TblName, (SELECT COUNT(*) FROM TblName) as cntRws
FROM `AllTbls` ORDER BY `id` ASC LIMIT 0,30;
But this returns an error:
#1146 - Table 'database.TblName' doesn't exist
I know that I can do this in multiple queries (using a loop in a programming language), but is it possible to do it in one query?
PS. I'm using MySQL v.5.7.28
The simple answer is: "you can't"
Table names are not supposed to be used like variables, to hold data, in this way. What you're supposed to have is one table:
tblContractCounts
Client, ContractCount
-------------------
IBM, 1
Microsoft, 3
Google, 2
Not three tables:
tblIBMContractCounts
ContractCount
1
tblMicrosoftContractCounts
ContractCount
3
tblGoogleContractCounts
ContractCount
2
If your number of tables is known and fixed you can perhaps remedy things by creating a view that unions them all back together, or embarking on an operation to put them all into one table, with separate views named the old names so things carry in working til you can change them. If new tables are added all the time it's a flaw in the data modelling and need to be corrected. In that case you'd have to use a programming language (front end or stored procedure) to build a single query:
//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)
It doesn't have to be your front end that does this - you could also do this in mysql and leverage the dynamic sql / EXECUTE. See THIS ANSWER how we can concatenate a string using logic like above so that the string contains an sql query and then execute the query. The information schema will give you the info you need to get a list of all current table names
But all you're doing is working around the fact that your data modelling is broken; I recommend to fix that instead
ps: the INFORMATION_SCHEMA has rough counts for tables with their names, which may suffice for your needs in this particular case
select table_name, table_rows from infornation_schema.tables where table_name like ...
I managed to solve the problem using the following stored procedure.
-- 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
$$
And then when you call the procedure
CALL sp_Count_Rows();
You get this result
I'm creating a pivot table and I'd like the column names to be something like value1, value2, value3....
CREATE TEMPORARY TABLE temp_table (
id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
value VARCHAR(255),
date DATETIME ,
person_id INT ) ;
Here's the part where I'm naming the column. I tried ID, but with multiple personIDs, it makes the id going in random. I was trying the INTEGER AUTO_INCREMENT, but that throws an error
SET SESSION group_concat_max_len = 1000000 ;
SELECT GROUP_CONCAT(DISTINCT CONCAT('MAX(IF(id = ''', c.id, ''', value, NULL)) AS "', **INTEGER auto_increment**, '"'))
INTO #column_sql1
FROM temp_table c ;
set #sql = concat("select person_id, ", #column_sql1, " from temp_table group by `person_id`");
select #sql;
prepare stmt from #sql;
execute stmt;
Is there any way for each value column to be numbered, so later when I select I can choose the 1st, 2nd, and 3rd column instead of using a different field for the dynamic column name?
I've also tried row_number and many other things. Nothing seems to work.
Thanks for any help.
Error Message:
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INTeger auto_increment, '"'))
INTO #column_sql1"
I checked some questions regarding this error and most of it experience this error on using "SELECT" function but in my case I am using CREATE TABLE IF NOT EXIST but experience this error, can you check my code to see what causes the error or if you guys know other way to do the same stuff.
I want to create a table for yearly payment actually that is supposed to be monthly but I am trying by year right now.
/* INSERT HERE THE LIST OF ALL EXISTING PAYMENT TABLES */
DROP TEMPORARY TABLE IF EXISTS T_distinctTable;
CREATE TEMPORARY TABLE T_distinctTable (
ctr int PRIMARY KEY AUTO_INCREMENT NOT NULL,
DisTable varchar (18)
);
INSERT INTO T_distinctTable (DisTable)
SELECT TABLE_NAME from information_schema.tables WHERE TABLE_SCHEMA = 'cams' and TABLE_NAME like concat ('%','Payment_20','%');
SET #endYearTemp = (select count(*) from T_distinctTable);
set #YearNow = (SELECT YEAR(CURDATE()));
set #TableName = concat('Payment_',#YearNow);
set #SQLTable = ('CREATE TABLE IF NOT EXISTS `', #TableName ,'` id int NOT NULL AUTO_INCREMENT, name CHAR(30),PRIMARY KEY (id)');
SELECT #SQLTable;
PREPARE stmt FROM #SQLTable;
EXECUTE stmt;
Use concat() to concatenate strings. Putting them in parenthesis and separate them with commas alone wouldn't do it. And you forgot the parenthesis around the column definitions of CREATE TABLE.
...
set #SQLTable = concat('CREATE TABLE IF NOT EXISTS `', #TableName ,'` (id int NOT NULL AUTO_INCREMENT, name CHAR(30),PRIMARY KEY (id))');
SELECT #SQLTable;
PREPARE stmt FROM #SQLTable;
EXECUTE stmt;
...
I'm trying to write a MySQL query which will update a blog post view counter if the user has not visited the post in the last 24 hours. I'm trying to write something like this (but this does not work):
IF EXISTS (
SELECT 1
FROM `posts-views`
WHERE
`ip` = '".$_SERVER['REMOTE_ADDR']."'
AND
`time` > ".($time-60*60*24)."
AND
`post` = $id
) THEN
NULL
ELSE
INSERT INTO `posts-views`
(`post`, `time`, `ip`, `user`)
VALUES
($id, $time, '".$_SERVER['REMOTE_ADDR']."', $me)
What's the correct way to fix the query?
From what I see you cannot use INSERT IGNORE in that case, but something like following should do the job :
INSERT INTO `posts-views`
(`post`, `time`, `ip`, `user`)
SELECT $id, $time, '".$_SERVER['REMOTE_ADDR']."', $me
FROM dual
WHERE NOT EXISTS (
SELECT 1
FROM `posts-views`
WHERE
`ip` = '".$_SERVER['REMOTE_ADDR']."'
AND
`time` > ".$time-60*60*24."
AND
`post` = $id
)
I completely omit escaping variables which definitely should be done in real code.
UPDATED - added from dual to avoid syntax error