How to return 0 if table empty, 1 otherwise - sql

In postgreSQL, how can i return a table containing 0 if my table is empty and a table containing 1 if my table has rows?
I need to do it in SQL, not using any other language

Use:
SELECT CASE
WHEN EXISTS (SELECT * FROM foo LIMIT 1) THEN 1
ELSE 0
END
EDIT: Added LIMIT 1 to speed up query.

Might be a hack, but it works.
SELECT count(*) FROM (SELECT 1 FROM table LIMIT 1) AS t;
The 1 selected in the sub-query could be whatever, it is just a place holder.
The LIMIT 1 should make the sub-query very fast, regardless of table-size.
Edit: Rewrote a bit. Previous use of LIMIT was wrong (didn't help on large tables as I intended).

Try:
select sign(count(*)) from mytable

maybe this is what you are looking for?
select min( c ) from (
select count(*) c
from mytab
union
select 1
from mytab
having count(*) > 1 )

SELECT, COUNT and LIMIT should do it.
-- see below SELECT COUNT(*) FROM X LIMIT 1
Edit: This doesn't work in Postgres (8.x at least). Please see the comments and here: http://postgresql.1045698.n5.nabble.com/window-function-count-and-limit-td3233588.html
Happy SQL'ing.

You can put this request in a stored procedure, with the table name as parameter :
CREATE OR REPLACE FUNCTION isEmpty(tableName text, OUT zeroIfEmpty integer) AS
$func$
BEGIN
EXECUTE format('SELECT COALESCE ((SELECT 1 FROM %s LIMIT 1),0)', tableName)
INTO zeroIfEmpty;
END
$func$ LANGUAGE plpgsql;
Then run this function like this :
SELECT * FROM isEmpty('my_table_name');
So you can call it with any of your table's name

I don't think that's possible using nothing but SQL. Why can't you use any other language?

Related

Displaying an alternative result when derrived table is empty

I have this sql code where I try to display an alternative value as a result whenever the table is empty or the the single column of the top row when it is not
select top 1 case when count(*)!=0 then derrivedTable.primarykey
else 0 end endCase
from
(
select top 1 m.primarykey
from mytable m
where 0=1
)derrivedTable
The problem is that when I run this, I get the error message "column 'derrivedTable.primarykey' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause."
But when I put 'derrivedTable.primarykey' in the group by clause, I just get an empty table.
Does anyone hve a solution?
thanks in advance
You can use aggregation:
select coalesce(max(m.primarykey), 0)
from mytable m;
An aggregation query with no group by always returns exactly one row. If the table is empty (or all rows are filtered out), then the aggregation functions -- except for COUNT() -- return NULL -- which can be transformed to a value using COALESCE().
Such a construct makes me worry. If you are using this to set the primary key on an insert, then you should learn about identity columns or sequences. The database will do the work for you.
Can you try this below script-
SELECT
CASE
WHEN COUNT(*) = 1 THEN derrivedTable.primarykey
ELSE 0
END endCase
FROM
(
SELECT TOP 1 m.primarykey
FROM mytable m
WHERE 0 = 1
) derrivedTable
derrivedTable.primarykey;

Fastest way to determine if record exists

As the title suggests... I'm trying to figure out the fastest way with the least overhead to determine if a record exists in a table or not.
Sample query:
SELECT COUNT(*) FROM products WHERE products.id = ?;
vs
SELECT COUNT(products.id) FROM products WHERE products.id = ?;
vs
SELECT products.id FROM products WHERE products.id = ?;
Say the ? is swapped with 'TB100'... both the first and second queries will return the exact same result (say... 1 for this conversation). The last query will return 'TB100' as expected, or nothing if the id is not present in the table.
The purpose is to figure out if the id is in the table or not. If not, the program will next insert the record, if it is, the program will skip it or perform an UPDATE query based on other program logic outside the scope of this question.
Which is faster and has less overhead? (This will be repeated tens of thousands of times per program run, and will be run many times a day).
(Running this query against M$ SQL Server from Java via the M$ provided JDBC driver)
EXISTS (or NOT EXISTS) is specially designed for checking if something exists and therefore should be (and is) the best option. It will halt on the first row that matches so it does not require a TOP clause and it does not actually select any data so there is no overhead in size of columns. You can safely use SELECT * here - no different than SELECT 1, SELECT NULL or SELECT AnyColumn... (you can even use an invalid expression like SELECT 1/0 and it will not break).
IF EXISTS (SELECT * FROM Products WHERE id = ?)
BEGIN
--do what you need if exists
END
ELSE
BEGIN
--do what needs to be done if not
END
SELECT TOP 1 products.id FROM products WHERE products.id = ?; will outperform all of your suggestions as it will terminate execution after it finds the first record.
Nothing can beat -
SELECT TOP 1 1 FROM products WHERE id = 'some value';
You don't need to count to know if there is a data in table. And don't use alias when not necessary.
SELECT CASE WHEN EXISTS (SELECT TOP 1 *
FROM dbo.[YourTable]
WHERE [YourColumn] = [YourValue])
THEN CAST (1 AS BIT)
ELSE CAST (0 AS BIT) END
This approach returns a boolean for you.
Don't think anyone has mentioned it yet, but if you are sure the data won't change underneath you, you may want to also apply the NoLock hint to ensure it is not blocked when reading.
SELECT CASE WHEN EXISTS (SELECT 1
FROM dbo.[YourTable] WITH (NOLOCK)
WHERE [YourColumn] = [YourValue])
THEN CAST (1 AS BIT)
ELSE CAST (0 AS BIT) END
You can also use
If EXISTS (SELECT 1 FROM dbo.T1 WHERE T1.Name='Scot')
BEGIN
--<Do something>
END
ELSE
BEGIN
--<Do something>
END
Below is the simplest and fastest way to determine if a record exists in database or not
Good thing is it works in all Relational DB's
SELECT distinct 1 products.id FROM products WHERE products.id = ?;
SELECT COUNT(*) FROM products WHERE products.id = ?;
This is the cross relational database solution that works in all databases.
For those stumbling upon this from MySQL or Oracle background - MySQL supports the LIMIT clause to select a limited number of records, while Oracle uses ROWNUM.
For MySql you can use LIMIT like below (Example shows in PHP)
$sql = "SELECT column_name FROM table_name WHERE column_name = 'your_value' LIMIT 1";
$result = $conn->query($sql);
if ($result -> num_rows > 0) {
echo "Value exists" ;
} else {
echo "Value not found";
}
create or replace procedure ex(j in number) as
i number;
begin
select id into i from student where id=j;
if i is not null then
dbms_output.put_line('exists');
end if;
exception
when no_data_found then
dbms_output.put_line(i||' does not exists');
end;
I've used this in the past and it doesn't require a full table scan to see if something exists. It's super fast...
UPDATE TableName SET column=value WHERE column=value
IF ##ROWCOUNT=0
BEGIN
--Do work
END
SQL SERVER 2012+
SELECT IIF((SELECT TOP 1 1 FROM dbo.[YourTable] WHERE [YourColumn] = [YourValue]) IS NULL, 0, 1)
May you wanna try my way:
IF (SELECT TOP 1 1 FROM [TableName]) = 1
BEGIN
--Do work
END

SQL: Get a random entry iff condition is false

Using Firebird:
I want to select a random entry in the table if the first SQL query returns 0 rows. Is there anyway to combine these two queries?
SELECT * FROM table WHERE cond=1;
SELECT FIRST 1 * FROM table ORDER BY rand();
Im using ExecuteNativeQuery on the java-side which takes basic SQL statements. Sadly, If-Else statements don't work. And if i could make a single query to the database instead of two, that would make my code appear faster.
try this: Not sure but think it will work...
Select FIRST 1 t1.*
FROM table t1
left Join Table t2
On t2.pk = t1.pk
And t2.cond=1
ORDER BY Case When t2.Cond = 1
Then 0 Else rand() End
if(exists(select 1 from table where cond=1))
SELECT * FROM table WHERE cond=1;
else
SELECT FIRST 1 * FROM table ORDER BY rand();
something like this, though I forgot whether the then keyword is needed in if statements in FirebirdSQL databases.

Best way to write a named SQL query that returns if row exists?

So I have this SQL query,
<named-query name="NQ::job_exists">
<query>
select 0 from dual where exists (select * from job_queue);
</query>
</named-query>
Which I plan to use like this:
Query q = em.createNamedQuery("NQ::job_exists");
List<Integer> results = q.getResultList();
boolean exists = !results.isEmpty();
return exists;
I am not very strong in SQL/JPA however, and was wondering whether there is a better way of doing it (or ways to improve it). Should I for example, write (select jq.id from job_queue jq) instead of using a star??
EDIT:This call is very performance critical in our app.
EDIT:Did some performance testing, and while the differences were almost negligible, I finally decided to go with:
select distinct null
from dual
where exists (
select null from job_queue
);
IF you are using EXISTS Oracle I recommend using null:
select null
from dual where exists (select null from job_queue);
The following will be the one with lower cost on Oracle:
select null
from job_queue
where rownum = 1;
Update: To include the case when there are no rows on table you can run the following query:
select count(*)
from (select null
from job_queue
where rownum = 1);
With this query you have a optimum plan and only two possible results: 1 if there are rows and 0 if there are no rows.
If you do an "exists" then it will stop looking as soon as it finds a match. This can stop it from doing a full table scan. Same with TOP 1 if you don't have an ORDER BY. If you do a TOP 1 ID and ID is in an index it might use the index and not even go to the table at all. Stopping the full table scan is where the biggest saving in performance is.
Another small savings is that if you do "SELECT 1" or "SELECT COUNT(1)" instead of "SELECT * " or "SELECT COUNT(*)" it saves the work of getting the table structure.
So I would go with:
SELECT TOP 1 1 AS Found
FROM job_queue
Then:
return !results.isEmpty();
This is the least amount of work that I can think of.
For Oracle it would be:
SELECT 1
FROM job_queue
WHERE rownum<2;
Or:
Set Rowcount 1
SELECT 1
FROM job_queue
Why not just do:
select count(*) as JobCount from job_queue
If JobCount = 0, then there's your answer!

Sql query that numerates the returned result

How to write one SQL query that selects a column from a table but returns two columns where the additional one contains an index of the row (a new one, starting with 1 to n). It must be without using functions that do that (like row_number()).
Any ideas?
Edit: it must be a one-select query
You can do this on any database:
SELECT (SELECT COUNT (1) FROM field_company fc2
WHERE fc2.field_company_id <= fc.field_company_id) AS row_num,
fc.field_company_name
FROM field_company fc
SET NOCOUNT ON
DECLARE #item_table TABLE
(
row_num INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, --THE IDENTITY STATEMENT IS IMPORTANT!
field_company_name VARCHAR(255)
)
INSERT INTO #item_table
SELECT field_company_name FROM field_company
SELECT * FROM #item_table
if you are using Oracle or a database that supports Sequence objects, make a new db sequence object for this purpose. Next create a view, and run this.
insert into the view as select column_name, sequence.next from table
In mysql you can :
SELECT Row,Column1
FROM (SELECT #row := #row + 1 AS Row, Column1 FROM table1 )
As derived1
I figured out a hackish way to do this that I'm a bit ashamed of. On Postgres 8.1:
SELECT generate_series, (SELECT username FROM users LIMIT 1 OFFSET generate_series) FROM generate_series(0,(SELECT count(*) - 1 FROM users));
I believe this technique will work even if your source table does not have unique ids or identifiers.
On SQL Server 2005 and higher, you can use OVER to accomplish this:
SELECT rank() over (order by company_id) as rownum
, company_name
FROM company