SELECT no rows and no columns? - mysql

Is it possible to write a SELECT statement, which returns dataset with zero rows and zero columns?

A dataset will always have at least 1 column, even if it contains no data.
SELECT NULL;
EDIT:
As pointed out by #eggyal , above syntax will return a null row.
His query select null from dual where false; wont return a row.

Not possible in my opinion. You will get at least one column, but no rows.
Select null from yourTable where 1 = 2;

This works for postgresql:
create table test22 ();
select * from test22;

it's normally used for Creating empty Table from an Existing Table
CREATE TABLE NEW_TABLE_NAME AS
SELECT *
FROM EXISTING_TABLE_NAME
where 1=2

No, but it is possible to return a query with no rows. In order to do this without referencing any tables, you can use a subquery:
SELECT NULL FROM (SELECT NULL) AS temp WHERE false;
This query will have one (empty) column, but no rows.
I've used the above construct when there is a query that is different in different cases, followed by a code loop that iterates through the results, and under some conditions you want to make it skip the loop. Replacing the query with the one above is a way of returning empty results and thus skipping the loop without an if block. Because the query contains no table names, that aspect of the code never needs to be changed, and for this reason I prefer it to adding a condition like WHERE false in an existing query.
I prefer this solution to the more concise one referencing dual because that construct is not supported in PostgreSQL; this solution works with any backend that supports subqueries.

Related

Can somebody elaborate on the `SELECT LAST_INSERT_ID()` statement?

I have always had the understanding that you use SELECT to select columns from a table. However, I was thrown off when I saw SELECT LAST_INSERT_ID(). I understand what it does... but I don't understand how we can simply just ask for the last inserted id like that. Isn't it true that the SELECT keyword expects to see column names immediately afterwards... so how does that function call satisfy that requirement?
The SELECT statement normally works with a FROM clause to select columns -- and expressions on columns and constants -- from rows in a table.
Without the FROM clause, a SELECT simply evaluates the expressions and returns one row. The function LAST_INSERT_ID() is simply an expression that returns a value, so:
SELECT LAST_INSERT_ID()
returns a result set with single row with a single (unnamed) column.
Some databases do not like the idea of a SELECT without a FROM. Oracle is one of them. It requires a FROM clause and provides a table with one column and one row. MySQL also supports dual, so you could write:
SELECT LAST_INSERT_ID()
FROM dual;
This is handy, if you want to include a WHERE clause with the SELECT (the WHERE requires a FROM in MySQL).

MySql Duplicated rows string comparation performance

I have a table with more then 2 million records,
I need to find duplication records in column with string type additionaly I have index for this field.
I have next query:
select m.* from member as m
where lower(m.username) in
(select lower(b.username) from member as b
where b.Username like 'a%'
group by b.username
having count(b.username) >= 2);
sub-query return only 4 records less then 0.2 seconds, but if I use them in where conditions section, this query working very long time and never return results....
I have tried to run next query, that theoretically the same logic:
select * from member as m where lower(Username) in (lower('a1'),
lower('a2'),lower('a3'),lower('a4'));
and it works fine and fast.
what is the issues ?
additionally I would like to run query with out where b.Username like 'a%' part?
In common case MySQL can not use index for IN subqueries
This is sad, but, actually, MySQL can not recognize "constant subqueries". What does it mean? It means that if you have a subquery that returns static list of values - and you use that in IN within another query, MySQL will not use index (by range).
Why it is so?
Actually, the most correct point is - because MySQL treats following queries:
.. WHERE `field` IN ('foo', 'bar', 'baz')
and
.. WHERE `field` IN (SELECT `col` FROM t)
-as different queries (I'm assuming that column col in table t in second query have same values, i.e. 'foo', 'bar', 'baz'). First query is equivalent for it's "expected" case, i.e. for range of values. But second query is equal for = ANY subquery - and so MySQL will not use index for that.
What to do
Actually, your case and cases similar to it - are cases when it's better to split your query into two parts. First part will be retrieve static list of values from your table. Second part will substitute result of your first part into IN clause and then you'll get index using.
Alternative - you can use JOIN syntax for table to itself. That may seems useful if you want to resolve an issue with one query (or if your list is too long)

Select Left(columnA,2) or right(columnA,1)

Is there a way in MySql to use an either or in a select column. For instance
select left(columnA,2) or right(columnA,1) as columnAlias, sum(columnB)
from table
where ((left(columnA,2) in ('aa','bb','cc')) or (right(columnA,1) in ('a,','b','c')))
group by columnAlias
what I have is a table where either the first 2 characters of the column or the last character of the column indicates the facility. I need to sum the values by facility. A union gets me part way there then I could loop through the resulting dataset and sum things up in the code (or do a stored proc to return the sums), but I am wondering if there is a way to just get it from the query.
I've tried using the union query as an on the fly temp table and doing the select and group on that but if there are no records returned from either of the select statments then it throws a "column columnA cannot be null error.
Also tried with the syntax above, but not getting the results I am expecting. Any other ways to do this through the query?
using a CASE would prob be your best bet here.
http://dev.mysql.com/doc/refman/5.0/en/case-statement.html

What does it mean by select 1 from table?

I have seen many queries with something as follows.
Select 1
From table
What does this 1 mean, how will it be executed and, what will it return?
Also, in what type of scenarios, can this be used?
select 1 from table will return the constant 1 for every row of the table. It's useful when you want to cheaply determine if record matches your where clause and/or join.
SELECT 1 FROM TABLE_NAME means, "Return 1 from the table". It is pretty unremarkable on its own, so normally it will be used with WHERE and often EXISTS (as #gbn notes, this is not necessarily best practice, it is, however, common enough to be noted, even if it isn't really meaningful (that said, I will use it because others use it and it is "more obvious" immediately. Of course, that might be a viscous chicken vs. egg issue, but I don't generally dwell)).
SELECT * FROM TABLE1 T1 WHERE EXISTS (
SELECT 1 FROM TABLE2 T2 WHERE T1.ID= T2.ID
);
Basically, the above will return everything from table 1 which has a corresponding ID from table 2. (This is a contrived example, obviously, but I believe it conveys the idea. Personally, I would probably do the above as SELECT * FROM TABLE1 T1 WHERE ID IN (SELECT ID FROM TABLE2); as I view that as FAR more explicit to the reader unless there were a circumstantially compelling reason not to).
EDIT
There actually is one case which I forgot about until just now. In the case where you are trying to determine existence of a value in the database from an outside language, sometimes SELECT 1 FROM TABLE_NAME will be used. This does not offer significant benefit over selecting an individual column, but, depending on implementation, it may offer substantial gains over doing a SELECT *, simply because it is often the case that the more columns that the DB returns to a language, the larger the data structure, which in turn mean that more time will be taken.
If you mean something like
SELECT * FROM AnotherTable
WHERE EXISTS (SELECT 1 FROM table WHERE...)
then it's a myth that the 1 is better than
SELECT * FROM AnotherTable
WHERE EXISTS (SELECT * FROM table WHERE...)
The 1 or * in the EXISTS is ignored and you can write this as per Page 191 of the ANSI SQL 1992 Standard:
SELECT * FROM AnotherTable
WHERE EXISTS (SELECT 1/0 FROM table WHERE...)
it does what it says - it will always return the integer 1. It's used to check whether a record matching your where clause exists.
select 1 from table is used by some databases as a query to test a connection to see if it's alive, often used when retrieving or returning a connection to / from a connection pool.
The result is 1 for every record in the table.
To be slightly more specific, you would use this to do
SELECT 1 FROM MyUserTable WHERE user_id = 33487
instead of doing
SELECT * FROM MyUserTable WHERE user_id = 33487
because you don't care about looking at the results. Asking for the number 1 is very easy for the database (since it doesn't have to do any look-ups).
Although it is not widely known, a query can have a HAVING clause without a GROUP BY clause.
In such circumstances, the HAVING clause is applied to the entire set. Clearly, the SELECT clause cannot refer to any column, otherwise you would (correct) get the error, "Column is invalid in select because it is not contained in the GROUP BY" etc.
Therefore, a literal value must be used (because SQL doesn't allow a resultset with zero columns -- why?!) and the literal value 1 (INTEGER) is commonly used: if the HAVING clause evaluates TRUE then the resultset will be one row with one column showing the value 1, otherwise you get the empty set.
Example: to find whether a column has more than one distinct value:
SELECT 1
FROM tableA
HAVING MIN(colA) < MAX(colA);
If you don't know there exist any data in your table or not, you can use following query:
SELECT cons_value FROM table_name;
For an Example:
SELECT 1 FROM employee;
It will return a column which contains the total number of rows & all rows have the same constant value 1 (for this time it returns 1 for all rows);
If there is no row in your table it will return nothing.
So, we use this SQL query to know if there is any data in the table & the number of rows indicates how many rows exist in this table.
If you just want to check a true or false based on the WHERE clause, select 1 from table where condition is the cheapest way.
This means that You want a value "1" as output or Most of the time used as Inner Queries because for some reason you want to calculate the outer queries based on the result of inner queries.. not all the time you use 1 but you have some specific values...
This will statically gives you output as value 1.
I see it is always used in SQL injection,such as:
www.urlxxxxx.com/xxxx.asp?id=99 union select 1,2,3,4,5,6,7,8,9 from database;
These numbers can be used to guess where the database exists and guess the column name of the database you specified.And the values of the tables.
it simple means that you are retrieving the number first column from table ,,,,means
select Emply_num,Empl_no From Employees ;
here you are using select 1 from Employees;
that means you are retrieving the Emply_num column.
Thanks
The reason is another one, at least for MySQL. This is from the MySQL manual
InnoDB computes index cardinality values for a table the first time that table is accessed after startup, instead of storing such values in the table. This step can take significant time on systems that partition the data into many tables. Since this overhead only applies to the initial table open operation, to “warm up” a table for later use, access it immediately after startup by issuing a statement such as SELECT 1 FROM tbl_name LIMIT 1
This is just used for convenience with IF EXISTS(). Otherwise you can go with
select * from [table_name]
Image In the case of 'IF EXISTS', we just need know that any row with specified condition exists or not doesn't matter what is content of row.
select 1 from Users
above example code, returns no. of rows equals to no. of users with 1 in single column

MySQL nested queries execution

I am writing a nested MySQL query where a subquery returns more than one row and hence the query can not be executed.
Can anyone suggest me a solution for this problem?
Thanks in advance.
An error about a subquery returning more than one value says to me that you're attempting a straight value comparison, like this:
WHERE col = (SELECT col2 FROM TABLE_2)
The solution depends on the data coming from the subquery - do you want the query to use all the values being returned? If yes, then change the equals sign for an IN:
WHERE col IN (SELECT col2 FROM TABLE_2)
Otherwise, you need to correct the subquery so it only ever returns one value. The MAX or MIN aggregate functions are a possibliity - they'll return the highest or lowest value. It could just be a matter of correlating the subquery:
FROM TABLE_1 t1
WHERE t1.col = (SELECT MAX(t2.col2)
FROM TABLE_2 t2
WHERE t2.fk_col = t1.id) -- correlated example
As Tabhaza points out, a subquery generally doesn't return more than one column (though some databases support tuple matching), in which case you need to define a derived table/inline view and join to it.
Would've been nice to have more information on the issue you're having...
Try joining to a derived table rather than doing a subquery; it will allow you to return multiple fields:
SELECT a.Field1, a.Field2, b.Field3, b.Field4
FROM table1 a INNER JOIN
(SELECT c.Field3, c.Field4, c.Key FROM table2 as c) as b ON a.Key = b.Key
WHERE ...
this sounds like a logic problem, not a syntax problem.
why is the subquery returning more than one row?
why do you have that in a place that requires only one row?
you need to restructure something to fit these two things together. without any indication of your system, your query, or your intent, it is very hard to help further.
If the database says you are returning more than one row, you should listen to what it says and change your query so that it only returns one row.
This is a problem in your logic.
Change the query so that it only returns one row.
Think about why the query is returning more than one row, and determine how to get the query to return just the single row you need from that result.
Use a LIMIT clause on the subquery so it always returns a maximum of 1 row
You could add a LIMIT 1 to the subquery so the top query only considers the first result. You can also sort the results from the subquery before doing the LIMIT, to return the result with the highest/lowest X. But make sure that that's actually what you want to happen, as the multi-row subquery is often a symptom of an underlying problem.