Select query with multiple where clauses - java

I have a list of serial numbers: 111111, 222222, AAAAAA, FFFFFF and I want to return a corresponding value or null from a table depending on whether or not the value exists.
Currently I loop through my list of serial numbers, query using the following statement:
"SELECT cnum FROM table WHERE serial_num = " + serialNumber[i];
and then use the value if one is returned.
I would prefer to do this is one query and get results similar to:
Row | cnum
------------
1 | 157
2 | 4F2
3 | null
4 | 93O
5 | null
6 | 9F3
Is there a query to do this or am I stuck with a loop?

It sounds as if you have some sort of Java Array or Collection of serial numbers, and perhaps you want to check to see if these numbers are found in the DB2 table, and you'd like to do the whole list all at once, rather than one at a time. Good thinking.
So you want to have a set of rows with which you can do a left join to the table, with null indicating that the corresponding serial was not in the table. Several answers have started to use this approach. But they are not returning your row number, and they are using SELECT UNION's which seems a round-about way to get what you want.
VALUES clause
Your FROM clause can be a "nested-table-expression"
which can be a (fullselect)
with a correlation-clause. The (fullselect) can, in turn, be a VALUES clause. So you could have something like this:
FROM (VALUES (1, '157'), (2, '4F2'), (3, '5MISSING'), (4, '93O'), ...
) as Lst (rw, sn)
You can then LEFT JOIN this to the table, and get a two-column result table like you asked for:
SELECT Lst.rn, t.serial_num
FROM (VALUES (1, '157'), (2, '4F2'), (3, '5MISSING'), (4, '93O'), ...
) as Lst (rw, sn)
LEFT JOIN sometable t ON t.serial_num = Lst.sn
With this method, you will probably need a loop to build your dynamic SQL statement string, using the values from your collection.
If it was embedded SQL, we might be able to reference a host array variable containing your serial numbers. But alas, in Java I am not sure how to manage using the list directly in SQL, without using some loop.

If you use only an "in" it is not going to return null for the missing value forcing you to do some coding in the application (probably the most efficient way).
If you wanted the database to do all the work (may or may not be ideal) then
you would have to trick db2 into returning your list regardless.
Something like this might work, faking the null values to be returned from sysdummy with the common table expression (with part):
with all_serials as (
select '111111' as serialNumber from sysibm.sysdummy1 union all ,
select '222222' as serialNumber from sysibm.sysdummy1 union all ,
select 'AAAAAA' as serialNumber from sysibm.sysdummy1 union all ,
select 'FFFFFF' as serialNumber from sysibm.sysdummy1
)
select
t1.serialNumber,
t2.serialNumber as serialNumberExists
from
all_serials as t1 left outer join
/* Make sure the grain of the_Table is at "serialNumber" */
the_table as t2 on t1.serialNumber = t2.serialNumber

You can use the SQL IN keyword. You'd need to dynamically generate the list, but basically it'd look like:
SELECT cnum FROM table WHERE serial_num in ('111111', '2222222', '3333333', 'AAAAAAA'...)

Try something like:
select t.cnum
from
(select '111111' serial_num from sysibm.sysdummy1 union all
select '222222' serial_num from sysibm.sysdummy1 union all
select 'AAAAAA' serial_num from sysibm.sysdummy1 union all
select 'FFFFFF' serial_num from sysibm.sysdummy1) v
left join table t on v.serial_num = t.serial_num

I'm not sure if I get you correctly, but this could help:
String query = "SELECT cnum FROM table WHERE ";
for(int i = 0; i < serialNumber.length; i++)
query += "serial_num='" + serialNumber[i] + "' OR ";
query += "serial_num IS NULL "
System.out.println(query);

Related

i need to combine like and in query ..for e.g some thing like select * from table where first_name in ('%abc%','%def%') [duplicate]

In SQL I (sadly) often have to use "LIKE" conditions due to databases that violate nearly every rule of normalization. I can't change that right now. But that's irrelevant to the question.
Further, I often use conditions like WHERE something in (1,1,2,3,5,8,13,21) for better readability and flexibility of my SQL statements.
Is there any possible way to combine these two things without writing complicated sub-selects?
I want something as easy as WHERE something LIKE ('bla%', '%foo%', 'batz%') instead of this:
WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'
I'm working with SQl Server and Oracle here but I'm interested if this is possible in any RDBMS at all.
There is no combination of LIKE & IN in SQL, much less in TSQL (SQL Server) or PLSQL (Oracle). Part of the reason for that is because Full Text Search (FTS) is the recommended alternative.
Both Oracle and SQL Server FTS implementations support the CONTAINS keyword, but the syntax is still slightly different:
Oracle:
WHERE CONTAINS(t.something, 'bla OR foo OR batz', 1) > 0
SQL Server:
WHERE CONTAINS(t.something, '"bla*" OR "foo*" OR "batz*"')
The column you are querying must be full-text indexed.
Reference:
Building Full-Text Search Applications with Oracle Text
Understanding SQL Server Full-Text
If you want to make your statement easily readable, then you can use REGEXP_LIKE (available from Oracle version 10 onwards).
An example table:
SQL> create table mytable (something)
2 as
3 select 'blabla' from dual union all
4 select 'notbla' from dual union all
5 select 'ofooof' from dual union all
6 select 'ofofof' from dual union all
7 select 'batzzz' from dual
8 /
Table created.
The original syntax:
SQL> select something
2 from mytable
3 where something like 'bla%'
4 or something like '%foo%'
5 or something like 'batz%'
6 /
SOMETH
------
blabla
ofooof
batzzz
3 rows selected.
And a simple looking query with REGEXP_LIKE
SQL> select something
2 from mytable
3 where regexp_like (something,'^bla|foo|^batz')
4 /
SOMETH
------
blabla
ofooof
batzzz
3 rows selected.
BUT ...
I would not recommend it myself due to the not-so-good performance. I'd stick with the several LIKE predicates. So the examples were just for fun.
you're stuck with the
WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'
unless you populate a temp table (include the wild cards in with the data) and join like this:
FROM YourTable y
INNER JOIN YourTempTable t On y.something LIKE t.something
try it out (using SQL Server syntax):
declare #x table (x varchar(10))
declare #y table (y varchar(10))
insert #x values ('abcdefg')
insert #x values ('abc')
insert #x values ('mnop')
insert #y values ('%abc%')
insert #y values ('%b%')
select distinct *
FROM #x x
WHERE x.x LIKE '%abc%'
or x.x LIKE '%b%'
select distinct x.*
FROM #x x
INNER JOIN #y y On x.x LIKE y.y
OUTPUT:
x
----------
abcdefg
abc
(2 row(s) affected)
x
----------
abc
abcdefg
(2 row(s) affected)
With PostgreSQL there is the ANY or ALL form:
WHERE col LIKE ANY( subselect )
or
WHERE col LIKE ALL( subselect )
where the subselect returns exactly one column of data.
Another solution, should work on any RDBMS:
WHERE EXISTS (SELECT 1
FROM (SELECT 'bla%' pattern FROM dual UNION ALL
SELECT '%foo%' FROM dual UNION ALL
SELECT 'batz%' FROM dual)
WHERE something LIKE pattern)
The inner select can be replaced by another source of patterns like a table (or a view) in this way:
WHERE EXISTS (SELECT 1
FROM table_of_patterns t
WHERE something LIKE t.pattern)
table_of_patterns should contain at least a column pattern, and can be populated like this:
INSERT INTO table_of_patterns(pattern) VALUES ('bla%');
INSERT INTO table_of_patterns(pattern) VALUES ('%foo%');
INSERT INTO table_of_patterns(pattern) VALUES ('batz%');
I would suggest using a TableValue user function if you'd like to encapsulate the Inner Join or temp table techniques shown above. This would allow it to read a bit more clearly.
After using the split function defined at: http://www.logiclabz.com/sql-server/split-function-in-sql-server-to-break-comma-separated-strings-into-table.aspx
we can write the following based on a table I created called "Fish" (int id, varchar(50) Name)
SELECT Fish.* from Fish
JOIN dbo.Split('%ass,%e%',',') as Splits
on Name like Splits.items //items is the name of the output column from the split function.
Outputs
1 Bass
2 Pike
7 Angler
8 Walleye
I'm working with SQl Server and Oracle here but I'm interested if this is possible in any RDBMS at all.
Teradata supports LIKE ALL/ANY syntax:
ALL every string in the list.
ANY any string in the list.
┌──────────────────────────────┬────────────────────────────────────┐
│ THIS expression … │ IS equivalent to this expression … │
├──────────────────────────────┼────────────────────────────────────┤
│ x LIKE ALL ('A%','%B','%C%') │ x LIKE 'A%' │
│ │ AND x LIKE '%B' │
│ │ AND x LIKE '%C%' │
│ │ │
│ x LIKE ANY ('A%','%B','%C%') │ x LIKE 'A%' │
│ │ OR x LIKE '%B' │
│ │ OR x LIKE '%C%' │
└──────────────────────────────┴────────────────────────────────────┘
EDIT:
jOOQ version 3.12.0 supports that syntax:
Add synthetic [NOT] LIKE ANY and [NOT] LIKE ALL operators
A lot of times, SQL users would like to be able to combine LIKE and IN predicates, as in:
SELECT *
FROM customer
WHERE last_name [ NOT ] LIKE ANY ('A%', 'E%') [ ESCAPE '!' ]
The workaround is to manually expand the predicate to the equivalent
SELECT *
FROM customer
WHERE last_name LIKE 'A%'
OR last_name LIKE 'E%'
jOOQ could support such a synthetic predicate out of the box.
PostgreSQL LIKE/ILIKE ANY (ARRAY[]):
SELECT *
FROM t
WHERE c LIKE ANY (ARRAY['A%', '%B']);
SELECT *
FROM t
WHERE c LIKE ANY ('{"Do%", "%at"}');
db<>fiddle demo
Snowflake also supports LIKE ANY/LIKE ALL matching:
LIKE ANY/ALL
Allows case-sensitive matching of strings based on comparison with one or more patterns.
<subject> LIKE ANY (<pattern1> [, <pattern2> ... ] ) [ ESCAPE <escape_char> ]
Example:
SELECT *
FROM like_example
WHERE subject LIKE ANY ('%Jo%oe%','T%e')
-- WHERE subject LIKE ALL ('%Jo%oe%','J%e')
Use an inner join instead:
SELECT ...
FROM SomeTable
JOIN
(SELECT 'bla%' AS Pattern
UNION ALL SELECT '%foo%'
UNION ALL SELECT 'batz%'
UNION ALL SELECT 'abc'
) AS Patterns
ON SomeTable.SomeColumn LIKE Patterns.Pattern
One approach would be to store the conditions in a temp table (or table variable in SQL Server) and join to that like this:
SELECT t.SomeField
FROM YourTable t
JOIN #TempTableWithConditions c ON t.something LIKE c.ConditionValue
I have a simple solution, that works in postgresql at least, using like any followed by the list of regex. Here is an example, looking at identifying some antibiotics in a list:
select *
from database.table
where lower(drug_name) like any ('{%cillin%,%cyclin%,%xacin%,%mycine%,%cephal%}')
u can even try this
Function
CREATE FUNCTION [dbo].[fn_Split](#text varchar(8000), #delimiter varchar(20))
RETURNS #Strings TABLE
(
position int IDENTITY PRIMARY KEY,
value varchar(8000)
)
AS
BEGIN
DECLARE #index int
SET #index = -1
WHILE (LEN(#text) > 0)
BEGIN
SET #index = CHARINDEX(#delimiter , #text)
IF (#index = 0) AND (LEN(#text) > 0)
BEGIN
INSERT INTO #Strings VALUES (#text)
BREAK
END
IF (#index > 1)
BEGIN
INSERT INTO #Strings VALUES (LEFT(#text, #index - 1))
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
ELSE
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
RETURN
END
Query
select * from my_table inner join (select value from fn_split('ABC,MOP',','))
as split_table on my_table.column_name like '%'+split_table.value+'%';
Starting with 2016, SQL Server includes a STRING_SPLIT function. I'm using SQL Server v17.4 and I got this to work for me:
DECLARE #dashboard nvarchar(50)
SET #dashboard = 'P1%,P7%'
SELECT * from Project p
JOIN STRING_SPLIT(#dashboard, ',') AS sp ON p.ProjectNumber LIKE sp.value
May be you think the combination like this:
SELECT *
FROM table t INNER JOIN
(
SELECT * FROM (VALUES('bla'),('foo'),('batz')) AS list(col)
) l ON t.column LIKE '%'+l.Col+'%'
If you have defined full text index for your target table then you may use this alternative:
SELECT *
FROM table t
WHERE CONTAINS(t.column, '"bla*" OR "foo*" OR "batz*"')
I was also wondering for something like that. I just tested using a combination of SUBSTRING and IN and it is an effective solution for this kind of problem. Try the below query :
Select * from TB_YOUR T1 Where SUBSTRING(T1.Something, 1,3) IN ('bla', 'foo', 'batz')
In Oracle you can use a collection in the following way:
WHERE EXISTS (SELECT 1
FROM TABLE(ku$_vcnt('bla%', '%foo%', 'batz%'))
WHERE something LIKE column_value)
Here I have used a predefined collection type ku$_vcnt, but you can declare your own one like this:
CREATE TYPE my_collection AS TABLE OF VARCHAR2(4000);
I may have a solution for this, although it will only work in SQL Server 2008 as far as I know. I discovered that you can use the row-constructor described in https://stackoverflow.com/a/7285095/894974 to join a 'fictional' table using a like clause.
It sounds more complex then it is, look:
SELECT [name]
,[userID]
,[name]
,[town]
,[email]
FROM usr
join (values ('hotmail'),('gmail'),('live')) as myTable(myColumn) on email like '%'+myTable.myColumn+'%'
This will result in all users with an e-mail adres like the ones provided in the list.
Hope it's of use to anyone. The problem had been bothering me a while.
For Sql Server you can resort to Dynamic SQL.
Most of the time in such situations you have the parameter of IN clause based on some data from database.
The example below is a little "forced", but this can match various real cases found in legacy databases.
Suppose you have table Persons where person names are stored in a single field PersonName as FirstName + ' ' + LastName.
You need to select all persons from a list of first names, stored in field NameToSelect in table NamesToSelect, plus some additional criteria (like filtered on gender, birth date, etc)
You can do it as follows
-- #gender is nchar(1), #birthDate is date
declare
#sql nvarchar(MAX),
#subWhere nvarchar(MAX)
#params nvarchar(MAX)
-- prepare the where sub-clause to cover LIKE IN (...)
-- it will actually generate where clause PersonName Like 'param1%' or PersonName Like 'param2%' or ...
set #subWhere = STUFF(
(
SELECT ' OR PersonName like ''' + [NameToSelect] + '%'''
FROM [NamesToSelect] t FOR XML PATH('')
), 1, 4, '')
-- create the dynamic SQL
set #sql ='select
PersonName
,Gender
,BirstDate -- and other field here
from [Persons]
where
Gender = #gender
AND BirthDate = #birthDate
AND (' + #subWhere + ')'
set #params = ' #gender nchar(1),
#birthDate Date'
EXECUTE sp_executesql #sql, #params,
#gender,
#birthDate
If you are using MySQL the closest you can get is full-text search:
Full-Text Search, MySQL Documentation
This works for comma separated values
DECLARE #ARC_CHECKNUM VARCHAR(MAX)
SET #ARC_CHECKNUM = 'ABC,135,MED,ASFSDFSF,AXX'
SELECT ' AND (a.arc_checknum LIKE ''%' + REPLACE(#arc_checknum,',','%'' OR a.arc_checknum LIKE ''%') + '%'')''
Evaluates to:
AND (a.arc_checknum LIKE '%ABC%' OR a.arc_checknum LIKE '%135%' OR a.arc_checknum LIKE '%MED%' OR a.arc_checknum LIKE '%ASFSDFSF%' OR a.arc_checknum LIKE '%AXX%')
If you want it to use indexes, you must omit the first '%' character.
In Oracle RBDMS you can achieve this behavior using REGEXP_LIKE function.
The following code will test if the string three is present in the list expression one|two|three|four|five (in which the pipe "|" symbol means OR logic operation).
SELECT 'Success !!!' result
FROM dual
WHERE REGEXP_LIKE('three', 'one|two|three|four|five');
RESULT
---------------------------------
Success !!!
1 row selected.
Preceding expression is equivalent to:
three=one OR three=two OR three=three OR three=four OR three=five
So it will succeed.
On the other hand, the following test will fail.
SELECT 'Success !!!' result
FROM dual
WHERE REGEXP_LIKE('ten', 'one|two|three|four|five');
no rows selected
There are several functions related to regular expressions (REGEXP_*) available in Oracle since 10g version. If you are an Oracle developer and interested this topic this should be a good beginning Using Regular Expressions with Oracle Database.
No answer like this:
SELECT * FROM table WHERE something LIKE ('bla% %foo% batz%')
In oracle no problem.
In Teradata you can use LIKE ANY ('%ABC%','%PQR%','%XYZ%'). Below is an example which has produced the same results for me
--===========
-- CHECK ONE
--===========
SELECT *
FROM Random_Table A
WHERE (Lower(A.TRAN_1_DSC) LIKE ('%american%express%centurion%bank%')
OR Lower(A.TRAN_1_DSC) LIKE ('%bofi%federal%bank%')
OR Lower(A.TRAN_1_DSC) LIKE ('%american%express%bank%fsb%'))
;
--===========
-- CHECK TWO
--===========
SELECT *
FROM Random_Table A
WHERE Lower(A.TRAN_1_DSC) LIKE ANY
('%american%express%centurion%bank%',
'%bofi%federal%bank%',
'%american%express%bank%fsb%')
Sorry for dredging up an old post, but it has a lot of views. I faced a similar problem this week and came up with this pattern:
declare #example table ( sampletext varchar( 50 ) );
insert #example values
( 'The quick brown fox jumped over the lazy dog.' ),
( 'Ask not what your country can do for you.' ),
( 'Cupcakes are the new hotness.' );
declare #filter table ( searchtext varchar( 50 ) );
insert #filter values
( 'lazy' ),
( 'hotness' ),
( 'cupcakes' );
-- Expect to get rows 1 and 3, but no duplication from Cupcakes and Hotness
select *
from #example e
where exists ( select * from #filter f where e.sampletext like '%' + searchtext + '%' )
Exists() works a little better than join, IMO, because it just tests each record in the set, but doesn't cause duplication if there are multiple matches.
This is possible in Postgres using like or ilike and any or all with array. This is an example that worked for me using Postgres 9:
select id, name from tb_organisation where name ilike any (array['%wembley%', '%south%']);
And this prints out:
id | name
-----+------------------------
433 | South Tampa Center
613 | South Pole
365 | Bromley South
796 | Wembley Special Events
202 | Southall
111 | Wembley Inner Space
In T-SQL, this option works but it is not very fast:
CREATE FUNCTION FN_LIKE_IN (#PROC NVARCHAR(MAX), #ITENS NVARCHAR(MAX)) RETURNS NVARCHAR(MAX) AS BEGIN
--Search an item with LIKE inside a list delimited by "," Vathaire 11/06/2019
DECLARE #ITEM NVARCHAR(MAX)
WHILE CHARINDEX(',', #ITENS) > 0 BEGIN
SET #ITEM = LEFT(#ITENS, CHARINDEX(',', #ITENS) - 1)
--IF #ITEM LIKE #PROC
IF #PROC LIKE #ITEM
RETURN #PROC --#ITEM --1
ELSE
SET #ITENS = STUFF(#ITENS, 1, LEN(#ITEM) + 1, '')
END
IF #PROC LIKE #ITENS RETURN #PROC --#ITEM --1
RETURN NULL --0
END
Query:
SELECT * FROM SYS.PROCEDURES
WHERE DBO.FN_LIKE_IN(NAME, 'PRC%,SP%') IS NOT NULL
you can do this dynamically for a large number of elements, at the expense of performance, but it works.
DECLARE #val nvarchar(256),
#list nvarchar(max) = 'one,two,three,ten,five';
CREATE table #table (FIRST_NAME nvarchar(512), LAST_NAME nvarchar(512));
CREATE table #student (FIRST_NAME nvarchar(512), LAST_NAME nvarchar(512), EMAIL
nvarchar(512));
INSERT INTO #student (FIRST_NAME, LAST_NAME, EMAIL)
SELECT 'TEST', ' redOne' ,'test.redOne#toto.com' UNION ALL
SELECT 'student', ' student' ,'student#toto.com' UNION ALL
SELECT 'student', ' two' ,'student.two#toto.com' UNION ALL
SELECT 'hello', ' ONE TWO THREE' ,'student.two#toto.com'
DECLARE check_cursor CURSOR FOR select value from STRING_SPLIT(#list,',')
OPEN check_cursor
FETCH NEXT FROM check_cursor INTO #val
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #val
IF EXISTS (select * from #student where REPLACE(FIRST_NAME, ' ','')
like '%' + #val + '%' OR REPLACE(LAST_NAME, ' ','') like '%' + #val + '%')
BEGIN
INSERT INTO #table (FIRST_NAME, LAST_NAME )
SELECT TOP 1 FIRST_NAME, LAST_NAME VALUE from #student where
REPLACE(FIRST_NAME, ' ','') like '%' + #val + '%' OR REPLACE(LAST_NAME, ' ','')
like '%' + #val + '%'
END;
FETCH NEXT FROM check_cursor INTO #val
END
CLOSE check_cursor;
DEALLOCATE check_cursor;
SELECT * FROM #table;
DROP TABLE #table;
DROP TABLE #student;
use cursor in SQL SERVER and execute for every value:
table sample:
create table Gastos_ConciliacionExcluida(IdRegistro int identity(1,1), MascaraTexto nvarchar(50), Activa bit default 1, Primary key (IDRegistro))
insert into Gastos_ConciliacionExcluida(MascaraTexto) Values ('%Reembolso%')
alter procedure SP_Gastos_ConciliacionExcluidaProcesar
as
declare cur cursor for select MascaraTexto From Gastos_ConciliacionExcluida where Activa=1
declare #Txt nvarchar(50)
open cur
fetch next from cur into #Txt
while ##Fetch_Status = 0
begin
update Gastos_BancoRegistro set PresumibleNoConciliable = 1
where Concepto like #txt
fetch next from cur into #Txt
end
close cur
deallocate cur
do this
WHERE something + '%' in ('bla', 'foo', 'batz')
OR '%' + something + '%' in ('tra', 'la', 'la')
or
WHERE something + '%' in (select col from table where ....)

JPA Union Equivelant Need for Adding Constant to Query Result

I need union equivelant for Union. I know we can do this by joining selections but i couldn't do that for adding constant to query results. Here is my sql
SELECT MIN(t1.EXAMPLE_NUMBER)
FROM
(
SELECT 1 AS EXAMPLE_NUMBER
UNION ALL
SELECT EXAMPLE_NUMBER + 1
FROM selection.SELECTION
) t1
LEFT OUTER JOIN selection.SELECTION t2
ON t1.EXAMPLE_NUMBER = t2.EXAMPLE_NUMBER
WHERE t2.EXAMPLE_NUMBER IS NULL;
This query need for finding minimum unused integer for the column. Lets say:
EXAMPLE_NUMBER
1
4
5
I need to get 2 as a result for this case. That is the sql for this. So here is my question:
I use QueryDsl-JPA for this. Since JPA 2, i can't use UNION. So i can't do this sql with querydsl-jpa, i was thinking about go like this:
JPAQuery baseQuery = new JPAQuery(em);
SubQueryExpression handleNumberOne = baseQuery.select(Expressions.constant(1));
SubQueryExpression selectAvailableMinNumber = baseQuery.select(selection.exampleNumber.add(1)).from(selection);
baseQuery.union(handleNumberOne, selectAvailableMinNumber); // NO UNION AVAILABLE
Is it any available way to do this with querydsl-JPA? I don't want to include querydsl-sql library just for this reason, I'm looking for JPA style solution. What i tried so for to try adding constant (1 in my case) to result of select query without union. By this way I may able to continue. Any suggestion?
You do not have to generate all the numbers to get this information.
For all numbers except 1, you can do:
select s.example_number + 1
from selection s
where not exists (select 1
from selection s2
where s2.example_number = s.example_number + 1
)
fetch first 1 row only; -- or limit 1
If you also want to get "1" if it doesn't exist, then:
select (case when min_en > 1 then 1
else s.example_number + 1
end)
from selection s cross join
(select min(example_number) as min_en from selection) mins
where not exists (select 1
from selection s2
where s2.example_number = s.example_number + 1
)
fetch first 1 row only; -- or limit 1

How to separate between data selecting from multiple tables?

I want to search in 16 different tables, but I don't wanna repeat the "select from DB" 16 times; I think that's not really help in performance!!!
I am using:
query="SELECT * FROM table1, table2,..., table16 WHERE id=?";
Is it correct ??
my problem is how to separate between data of tables ??
also maybe I can get from one table two or more results for one "id"; So I want to know which data is from which table !!
.
Best regards,
Your query will not work, because you are trying to join those multiple tables, whereas what you want to do is search (filter) those 16 tables.
You could use a union all to do this in a single query:
select xxx, 'table1' as source_table
from table1
where id = ?
union all
select xxx, 'table2' as source_table
from table2
where id = ?
and so on. The second derived field source_table can be used to determine which table returned which result.
You have to list all fields using aliases for fields with same name, and prefix with table names.
For example :
query = "SELECT table1.id as id_1, table2.id as id_2, ... WHERE id_1 = 23"
Probably a very long query to write, but you have solution to generate and paste it : You can do this for example with FlySpeed SqlQuery (free for personal use)
FlySpeed SqlQuery will generate all aliases for you, and automatically prefix with table names.
A little clarification would help. If all 16 tables have the same fields and you want them in a continuous list, you can use UNION as suggested above. On the other hand, if there are only a few fields that match and you want to compare the values for each table side-by-side, you'll want to use joins and provide aliases with the table names, as also suggested above.
However, looking at the snippet of code you've provided, I'm going to guess that you're either building some kind of stored procedure or else implementing SQL in some other language. If that's the case, how about loading your table names into an array and using a for loop to build the query, such as the following psuedo-code:
tableList = ["table1", "table2"...]
fieldnames = ["field1", "field2"...]
query = "SELECT "
for i = 0 to count(tableList):
for j = 0 to count(fieldnames):
query = query + tablelist[i] + "." + fieldnames[j] + ", "
j++
i++
query = query + "FROM "
for i = 0 to count(tableList):
query = query + tableList[i] + ", "
i++
query = query + "WHERE " ...
And so forth. Much of this depends on what exactly you're looking to do, how often you're looking to do it, and how often the variables (like which tables or fields you're using) are going to change.

Static list MINUS select statement

I have a java program that returns a list of Long values (hundreds).
I would like to subtract to this list the values obtained from a select on an oracle database,
something like this:
SELECT 23 as num FROM DUAL UNION ALL
SELECT 17 as num FROM DUAL UNION ALL
SELECT 19 as num FROM DUAL UNION ALL
SELECT 67 as num FROM DUAL UNION ALL...
...
...
SELECT 68 as num FROM DUAL MINUS
SELECT NUM FROM MYTABLE
I presume that this operation has some performance issues...
Are there other better approaches?
Thank you
Case 1:
Use Global Temporary Tables (GTT):
CREATE GLOBAL TEMPORARY TABLE my_temp_table (
column1 NUMBER
) ON COMMIT DELETE ROWS;
Insert the List (Long value) into my_temp_table:
INSERT ALL
INTO my_temp_table (column1) VALUES (27)
INTO my_temp_table (column1) VALUES (32)
INTO my_temp_table (column1) VALUES (25)
.
.
.
SELECT 1 FROM DUAL;
Then:
SELECT * FROM my_temp_table
WHERE column1 NOT IN (SELECT NUM FROM MYTABLE);
Let me know if you have any issue.
Case 2:
Use TYPE table:
CREATE TYPE number_tab IS TABLE OF number;
SELECT column_value AS num
FROM TABLE (number_tab(1,2,3,4,5,6)) temp_table
WHERE NOT EXIST (SELECT 1 FROM MYTABLE WHERE MYTABLE.NUM = temp_table.num);
Assuming MyTable is much bigger than literal values, I think the best option is using a temporary table to store your values. This way your query is a lot cleaner.
If you are working in a concurrent environment (e.g. typical web app), use an id field, and delete when finished. Summarizing:
preliminary: create a table for temporary values TEMPTABLE(id, value)
for each transaction
get new unique/atomic id (new oracle sequence value, for example)
for each literal value: insert into temptable(new_id, value)
select * from temptable where id = new_id minus...
process result
delete from temp_table where id = new_id
Temporary tables are a good solution in oracle. This one can be used with an ORM persistence layer

How to display values from sql statement

I am using netbeans.
I have a table 'incident' with column 'priority' which can hold values priority 1 , priority 2.
I have created a jcombobox with 3 options - select all( to select all the rows) / priority 1(to select rows with priority 1 and so on) / priority 2. Options are passed through prioritybox.getSelected().
I want to know any possible sql statement so that if i select the option 'select all' , all the entries of the table should be selected.
If i choose priority 1
then the statement
select * from incident where priority='"+prioritybox.getSelected()+"';
gets executed correctly i.e. it select the rows which having priority=priority1. But if i select the option 'select all ' then this statement becomes invalid as no such row is there with priority value = select all.I don't want to use if-else . Any other possible solution??
You need to use if clause.
Go with the following code
String strSelect1 = "select * from table";
if(prioritybox.getSelectedItem()!="your option")
{ strSelect1=strSelect1+" where Priority='"+prioritybox.getSelectedItem()+"'"; };
Now keep on adding this if statements for rest of the fields.
For purely SQL you could do:
select * from incident where priority='"+prioritybox.getSelected()+"' OR '"+prioritybox.getSelected()+"' = 'select all';
However it's probably easier to add logic to add the where clause if the option is not select all.
You can pass special character '%' to query which will return all characters for that you need to replace = with like query and you need to set '%' as your 'SelectAll' value, your query can be like this
select * from incident where priority like '"+prioritybox.getSelected()+"';
String query="";
if(!prioritybox.getSelected().toString().equals("select all")){
query="select * from incident where priority='"+prioritybox.getSelected()+"'";
}
else {
query="select * from incident" ;
}

Categories