Mysql query vertical "\G" not working - mysql

I have a question about query data with vertical format, I tried it with \g or \G .
I referenced "4.5.1.6.2 Displaying Query Results Vertically" at https://dev.mysql.com/doc/refman/5.5/en/mysql-tips.html
But it not working and show error syntax at "\G"
My query :
select * from mytable \G . Always wrong.
From that, I just want to build final query like this:
Select "A","B","C","D" as "ColumnName" \G
Expect:
ColumnName
A
B
C
D
I tried with UNION or UNION ALL. but with several thousand record, it's slow performance.
And mysql version is : Server version- 5.6.17 - MySQL Community Server (GPL)
# Bernd Buffen
I show my query:
Select C.* from
(
( Select * from (Select "Value1" as newcolumn UNION ALL Select "Value2" as newcolumn UNION ALL ...<200.000 UNION ALL>) ) A
left join
(SELECT key,column1,column2,colum3 FROM supplier ) B
on A.newcolumn = B.key
) C
And handle query to database, I debug time from Begin to End, it spend from 1.30 to 2 minutes. It is not good.

The \G and \g features are just features of the command line client (as mentioned in the comments.)
MySQL when used from a programming API (even another program, like phpMyAdmin or a MySQL GUI) does not support \g or \G. It doesn't even "display" data. Display is done by the GUI program, instead.
However, even if you ran this query:
SELECT 'A', 'B', 'C', 'D' AS "ColumnName"\G
In the command line client, it would actually produce:
*************************** 1. row ***************************
A: A
B: B
C: C
ColumnName: D
1 row in set (0.01 sec)
This is because you've selected 4 columns in that query, and only named the last one 'ColumnName'.
If you want to see the rows of the table you would run:
SELECT *
FROM table_name\G
And then it would list each column, then a :, then the value.
Nevertheless, this would only work with the command line client.
If you're wanting to retrieve a key, value from the database via a programming API, the problem is definitely a bit trickier. A UNION is going to end up being what you want, e.g.:
SELECT 'column_name_1' AS key, GROUP_CONCAT(column_name_1) AS value
FROM table_name
UNION ALL
SELECT 'column_name_2' AS key, GROUP_CONCAT(column_name_2) AS value
FROM table_name
But yes, it's not likely to be efficient.
This isn't really the way databases are meant to be used - they're meant to be used as a table of data. I'd suggest you change the data to this format after you've retrieved it from MySQL. You might do this in an array, or similar.

Here is one more Sample.
DROP TEMPORARY TABLE IF EXISTS TMPV;
CREATE TEMPORARY TABLE `TMPV` (
`newcolumn` VARCHAR(32) NOT NULL DEFAULT '',
PRIMARY KEY (`newcolumn`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `TMPV` VALUES ('Value1'),('Value2'),('Value3'),('Value4'),('Value5'),('Value6');
SELECT A.*, s.`key`, s.`column1`, s.`column2`, s.`column2`
FROM `TMPV` A
LEFT JOIN supplier s
ON A.newcolumn = s.key;

Related

ERROR 1093 (HY000): Nested select on insert [duplicate]

Clearly the following is incorrect.
INSERT INTO `aTable` (`A`,`B`) VALUES((SELECT MAX(`A`) FROM `aTable`)*2),'name');
I get the value:
SQL query:
INSERT INTO `aTable` (`A`, `B` )
VALUES
(
(
SELECT MAX(`A`)
FROM `aTable`
) *2
, 'name'
)
MySQL said:
1093 - You can't specify target table 'aTable' for update in FROM clause
So, I'm trying to make a bitmap table, each row corresponds to one Bit, and has a 'map' value.
To insert in the table, I don't want to do two queries, I want to do one.
How should I do this?
No one commented on this, but since I am trying to make a bitmap, it should be * 2 not ^ 2, my mistake, please note that is why the comments often say ^ 2, it was an error in the version that the commenters read.
try:
insert into aTable select max(a)^2, 'name' from aTable;
or
insert into aTable select max(a)^2, 'name' from aTable group by B;
If you need a join, you can do this:
insert into aTable select max(a)^2, 'name' from aTable, bTable;
My "Server version" is "5.0.51b-community-nt MySQL Community Edition (GPL)"
Actually, you can alias the table on the insert. I've seen this question all over the place, but no one seems to have tried that. Use a subquery to get the max from the table, but alias the table in the subquery.
INSERT INTO tableA SET fieldA = (SELECT max(x.fieldA) FROM tableA x)+1;
A more complex example, where you have a corresponding secondary key and might be inserting the FIRST record for the corresponding secondary key:
INSERT INTO tableA SET secondaryKey = 123, fieldA = COALESCE((SELECT max(x.fieldA) FROM tableA x WHERE x.secondaryKey = 123)+1,1);
By aliasing the table, it doesn't throw the error and seems to work. I just did this while coding something, although I can't see if there area any silly syntax errors above, I would try that type of syntax.
I take it that INSERT ... SELECT isn't working? I see this in the documentation for it:
The target table of the INSERT
statement may appear in the FROM
clause of the SELECT part of the
query. (This was not possible in some
older versions of MySQL.) In this
case, MySQL creates a temporary table
to hold the rows from the SELECT and
then inserts those rows into the
target table.
Out of curiosity, which version of MySQL are you using?
I think you need to drop the "VALUES", and have a valid select statement.
see this link
I'm not particularly a mySQL guy, I use MSSQL mostly. But If you format the select statement correctly, It should work.
as soon as the Select is correct you can do this.

Select information from multiple tables with unique ID in the table name

Here is the scenario: I have tables stored in my monitoring application database using IDs as part of the table name. For instance, for 10 monitored devices, the device logs are stored in tables for each device with the device ID as part of the name, like this:
Device ID Table Name
1 device_logs.log_1
2 device_logs.log_2
I want to be able to :
select * from all device log tables where ID IN (a-list-of-IDs)
I reference this type of information a lot, and it would be easier to do it in a quick query and possibly a report. For some small list of devices, a union query works, but after about 4-5 devices, that gets too long. Programmatically, I can do this in python with string substitution, but how do you do it in MySQL as a query?
Adding a code segment I am trying to get to work, but struggling with the syntax:
drop table if exists tmp_logs;
create temporary table tmp_logs
(
device_name varchar(30) not null,
date datetime,
message varchar (255)
)
engine=innodb;
drop procedure if exists load_tmp_log_data;
delimiter #
create procedure load_tmp_log_data()
begin
declare vid int unsigned;
truncate table tmp_logs;
start transaction;
while vid in(4976,4956) do
insert into tmp_logs values
( SELECT
dev.device,
date,
message
FROM device_logs.logs_vid
inner join master_dev.legend_device dev on dev.id=vid
where date >= '2014-7-1'
and message not like '%HDMI%'
and message not like '%DVI%'
and message not like '%SIP%'
and message not like '%Completed%'
and message not like '%Template%'
and message not like '%collection%'
and message not like '%Cache%'
and message not like '%Disconnect%'
and message not like '%Row removed%'
and message not like '%detailed discovery%'
and message not like '%restarted%'
and message not like '%Auto Answer%'
);
end while;
commit;
end #
delimiter ;
call load_tmp_log_data();
select * from tmp_logs order by device_name;
You cannot dynamically specify the user name as a query in regular SQL. You could use a prepare statement with dynamic SQL.
An alternative is to set up the query as:
select l.*
from ((select l.*
from device_logs.log_1 l
where device_id = 1 and id in (list of ids)
) union all
(select l.*
from device_logs.log_2 l
where device_id = 2 and id in (list of ids)
) . . .
) l;
You need to repeat the conditions in each subquery -- that makes them more efficient. And, use union all instead of union to avoid duplication.
Fundamentally, though, having tables of the same structure is often a sign of poor database design. It would be much better to have a single table with a column specifying the id. Then your query would be really easy:
select l.*
from logs l
where id in (list of ids);
You could generate such a table by changing the application that creates the tables. Or you could generate such a table by using an insert trigger on each of the subtables. Or, if the data can be a day or so out of date, run a job that re-creates the table every night.

Query input must contain atleast one table or query

I have a query in access that is suppose to check whether the item already exists in the database before inserting it:
INSERT INTO FinalizedPrintedStickers
Values('0000846043-481-9-0',
'48IG - 1F Straight Panel ',
'481 ',
'0',
'0',
'',
'210',
'Printed')
WHERE NOT EXISTS(SELECT [SN] FROM FinalizedPrintedStickers Where SN = '0000846043-481-9-0')
Now, I've gotten this error before but usually it's when there's no table for example if you "select * from test table" and you type "Select *" and leave out the from clause you get the same error. But I have a table ? Perhaps my where not exists syntax is wrong?
Edit:
Ok, I've added a table "Dual" as suggested with code copy pasted from this question : Table-less UNION query in MS Access (Jet/ACE)
Attempting to add a constraint as shown gave me this error :
after i press ok it highlights the word "Check"
I've never really dealt with constraints (in access atleast..) my syntax is probably wrong
Edit 2:
Adding constraints using ctrl G command
And when I press enter...
Adding constraints using ADO:
And when i press run...
This is one of those cases where a Dual table can be helpful. A Dual table is a single-row table that can be used in the FROM clause of a query when you don't really need a source table but the SQL parser insists on there being one.
Some database systems (e.g., Oracle) provide a Dual virtual table as "standard equipment", but in Access we need to create our own. For an excellent description of the process check out HansUp's answer here.
So, once you have your [Dual] table in place, i.e.,
id
--
1
...then you can use this query do perform your INSERT (or not...):
INSERT INTO FinalizedPrintedStickers
(
SN,
Field2
)
SELECT
"0000846043-481-9-0" AS SN,
"48IG - 1F Straight Panel" AS Field2
FROM Dual
WHERE DCount("SN","FinalizedPrintedStickers","SN=""0000846043-481-9-0""")=0
try this you can use simple where Clause
INSERT INTO FinalizedPrintedStickers
Values('0000846043-481-9-0',
'48IG - 1F Straight Panel ',
'481 ',
'0',
'0',
'',
'210',
'Printed')
WHERE SN Not In(SELECT [SN] FROM FinalizedPrintedStickers Where SN = '0000846043-481-9-0');

MySQL: Select from coma separated list / list as table? "SELECT a FROM (1, 2, 3)"

Is it possible to do something like this (obviously this syntax does not work):
SELECT a FROM (1, 2, 3)
to get this:
| a |
+---+
| 1 |
| 2 |
| 3 |
?
That is I want to make rows from coma separated list, without using any table, or at least without creating table in db (maybe this is possible using something like temporary table?).
Maybe it is possible to get column of given values without using select, that is using some other sql statment? If it is not possible in MySQL, but possible in some other SQL it still would be interesting to know.
SELECT 1 a UNION ALL SELECT 2 a UNION ALL SELECT 3 a;
Would a temporary table be an option? Then I would have a suggestion which, admittedly, has more than 1 query:
-- DROP TEMPORARY TABLE tmp_list IF EXISTS;
CREATE TEMPORARY TABLE tmp_list (a INT);
INSERT INTO tmp_list (a) VALUES (1), (2), (3);
SELECT a FROM tmp_list;
If it is not possible in MySQL, but possible in some other SQL it still would be interesting to know.
In standard SQL this would be something like this
select *
from ( values (1), (2), (3) ) t
This works at least in PostgreSQL and DB2.
In PostgreSQL you can give the column a name by extending the alias (not sure if that column aliasing is part of the SQL standard).
select *
from ( values (1), (2), (3) ) t (id)
The following is an alternative to the above using a common table expression.
with my_values (id) as (
values (1), (2), (3)
)
select *
from my_values;
Since MariaDB v10.3.3 and MySQL v8.0.19 you can now do exactly that!
See docs: MariaDB, MySQL
MariaDB:
WITH mylist (a) AS (VALUES (1),(2),(3))
SELECT a FROM mylist
I used a WITH here because MariaDB doesn't supply nice column names for VALUES .... You can use it in a union without column names:
SELECT 1 AS a UNION ALL VALUES (2),(3)
And although the docs don't appear to mention it, you can even use it as a top-level query:
VALUES (1),(2),(3) ORDER BY 1 DESC
The actual column names are in fact the just first row of values, so you can even do this (though it's inelegant, and you can run into duplicate column name errors):
SELECT `4` AS a FROM (VALUES (4),(5),(6)) mylist
MySQL:
I don't have an instance of MySQL v8.0.19 to test against right now, but according to the docs [EDIT: Tested successfully on MySQL v8.0.23 using dbfiddle.uk, see links in comment #2] either of these should work:
SELECT column_0 AS a FROM (VALUES ROW(1), ROW(2), ROW(3)) mylist
SELECT a FROM (VALUES ROW(1), ROW(2), ROW(3)) mylist(a)
Unlike MariaDB, MySQL supplies automatic column names column_0, column_1, column_2, etc., and also supports renaming all of a subquery's columns when referencing it.
I'm not sure, but this dev worklog page seems to suggest that MySQL has also implemented [EDIT: not implemented yet, as of v8.0.26] the shorter sytax (omitting "ROW", like MariaDB), or that they might at some poiint in the near future.

Is there an easy SELECT-Statement that creates an empty set?

Is there an easy and simple way to create a result table that has specified columns but zero rows? In set theory this is called an empty set, but since relational databases use multidimensional sets the term doesn't fit perfectly. I have tried these two queries, but both deliver exactly one row and not zero rows:
SELECT '' AS ID;
SELECT null AS ID;
But what I want is the same result as this query:
SELECT ID FROM sometable WHERE false;
I'm searching for a more elegant way because I don't want to have a table involved, so the query is independent from any database scheme. Also a generic query might be a bit faster (not that it would matter for such a query).
SELECT "ID" LIMIT 0;
Without any real tables.
Do note that most (My)SQL clients simply will display "Empty set". However, it actually does what you want:
create table test.test_table
select "ID" limit 0;
show create table test.test_table\G
Table: test_table
Create Table: CREATE TABLE `test_table` (
`ID` varchar(2) character set latin1 NOT NULL default ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
SELECT * FROM (SELECT NULL AS ID) AS x WHERE 1 = 0
You can use the DUAL pseudo-table.
SELECT whatever FROM DUAL WHERE 1 = 0
Check the documentation (look for the DUAL section).