faster way of process return - sql

I want to return last given passport from a database.
In Table1 there is only one passport info. In Table2 there are all passport info belong to every person.
My comparing code extremely slowly working, it takes too much time.
So, if there is any faster alternative code for my code please share it, Tanks befor.
from table1 t
where t.pass_date <
(select max(tb_datebeg) from table2 where tb_inn = t.tin)

We could phrase this as a join along with analytic functions:
WITH cte AS (
SELECT t1.*, MAX(t2.tb_datebeg) OVER (PARTITION BY t2.tb_inn) max_tb_datebeg
FROM table1 t1
INNER JOIN table2 t2 ON t2.tb_inn = t1.tin
)
SELECT *
FROM cte
WHERE pass_date < max_tb_datebeg;
The above query would benefit from the following index on table2:
CREATE INDEX idx2 ON table2 (tb_inn, tb_datebeg);

Related

Using MAX when selecting a high number of fields in a query

I understand some varieties of this question have been asked, but I could not find an answer to my specific scenario.
My query has over 50 fields being selected, and only one of them is an aggregate, using MAX(). On the GROUP BY clause, I would only like to pass two specific fields, name and UserID, not all 50 to make the query run. See small subset below.
SELECT
t1.name,
MAX(t2.id) as UserID,
t3.age,
t3.height,
t3.dob,
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id
LEFT JOIN table3 t3 ON t1.id = t3.id
GROUP BY t1.name, UserID
Is there any workaround or better approach to accomplish my goal?
The database is SQL Server and any help would be greatly appreciated.
Hmmm . . . What values do you want for the other fields? If you want the max() of one column for each id and code, you can do:
select t.*
from (select t.*, max(col) over (partition by id, code) as maxcol
from t
) t
where col = maxcol;
Given that id might be unique, you might want the maximum id as well as the other columns for each code:
select t.*
from (select t.*, max(id) over (partition by code) as maxid
from t
) t
where id = maxid;

How to make Query with IN in WHERE clause run faster

I have this query in Oracle11g :
SELECT DOC_ID,DOC_NAME,DESC
FROM TABLE1
WHERE DOC_ID NOT IN(
SELECT DOC_ID FROM TABLE2
)
The sql query above run very slow since i have so many data in the tables.
Is there any solution to get the same result with better performance and run faster?
Any help much appreciated.
Thanks.
Using WHERE EXISTS may have better performance:
SELECT DOC_ID,DOC_NAME,DESCr
FROM TABLE1 t1
WHERE not exists (
SELECT 1 FROM TABLE2 where
doc_id = t1.doc_id
);
Example: http://sqlfiddle.com/#!4/4b59e/3
I wouldn't use the in statement for that. If you join on what I imagine is one of your keys it should be much much faster:
select tb1.DOC_ID, tb1.DOC_NAME, tb1.DESC
from table1 tb1
left join table2 tb2
on tb1.DOC_ID = tb2.DOC_ID
where tab2.DOC_ID is not null

Multiple Indexes or Single One in a comparison between two large tables

I'm going to compare two tables on Oracle with about 10 million records in each one.
t1 (anumber, bnumber, cdate, ctime, duration)
t2 (fcode, anumber, bnumber, mdate, mtime, odate, otime, duration)
Rows in these tables are the information of calls from a number to the other for a specific month (august 2012).
For example (12345,9876,120821,120000,68) indicates a call from anumber=12345 to bnumber=9876 in date=2012/08/21 and time=12:08:21 which lasted for 68 seconds.
I want to find records that don't exists in one of these tables but exists in the other. My comparison query is like this
select t1.*
from table1 t1
where not exists(select t1.* from table2 t2
where t1.anumber = t2.anumber
and t1.cdate = t2.mdate
and t1.duration = t2.duration);
and my questions are:
Which kind of indexes is better to use? Multiple index on columns (anumber,cdate,duration) or single index on each of them?
Considering that the third column is duration of a call which could have a wide range, is it worth to create an index on it? doesn't it slower down my query?
What is the fastest way to find the differences between these table?
Is it better to loop through dates and execute my query with (cdate='A DATE MONTH') added to the where clause?
Compared to the above query how much slower is this one:
select t1.*
from table1 t1
where not exists (select t1.*
from table2 t2
where t1.anumber = t2.anumber
and t1.bnumber like '%t2.bnumber%'
and t1.cdate = t2.mdate
and t1.duration = t2.duration);
select * from t1
minus
select * from t2
don't use indexes, you want to scan all 10 million rows in both tables, therefore a TABLE_ACCESS_FULL is rather in this case.
try this way:
select t1.*
from table1 t1
where (t1.anumber, t1.date, t1.duration) not in (select t2.anumber, t2.date, t2.duration
from table2 t2);
see the explain, if good then don't creat indexes, or create like this
create index idx_anum_dat_dur on table2(anumber, date, duration)
query performance depends on the result of which will return, you must to see the explain and try different variants
Your query is equivalient to:
select t1.*
from table1 t1
WHERE t1.bnumber like '%t2.bnumber%' -- << like 'Literal' !!!
AND NOT EXISTS (
select *
from table2 t2
where t2.anumber = t1.anumber
and t2.cdate = t1.mdate
and t2.duration = t1.duration
);
(table references inside quotes are not expanded! Is this the OP's intention ??? )

selecting the most recent rows from database with multiple return set

Normally I would do
select top (1) * from table where id active = '1' and doc_type_id = '404'
to get the latest row.
However I'm using IN to get results back. Plus a join.
select t1.*
from table1 t1 left join table2 t2 on (t1.propid = t2.propid)
where t2.caseid in ('100','101') and t1.active = '1' and b.doc_type_id = '404'
This query here returns the documents. However there are multiple documents of the same type.
And if each one has 10 docs I need only the latest one.
I would want to retrieve only the latest 1 doc for each from the database.
I hope I explained myself :)
Without seeing the return types you are going for, it sounds like you need to use a GROUP BY and/or a MAX. If that does not help solve your problem, could you please post a sample data set and what you expect?
You might even be able to use partitioning and/or ROW_NUMBER()
UPDATE BASED ON COMMENTS
WITH myCTE
AS
(
SELECT t1.*,
ROW_NUMBER() OVER (PARTITION BY t2.caseid ORDER BY LastSavedDate DESC) AS RowNumber
FROM table1 t1
LEFT JOIN table2 t2
ON t1.propid = t2.propid
WHERE t2.caseid in ('100','101')
AND t1.active = '1' AND b.doc_type_id = '404'
)
SELECT *
FROM myCTE
WHERE RowNumber = 1;
This MIGHT work for you based on your comments
This is the ideal scenario for window functions. They are exactly what you need. Take a look at over keyword.

In SQL, how can I perform a "subtraction" operation?

Suppose I have two tables, which both have user ids. I want to perform an operation that would return all user IDS in table 1 that are not in table 2. I know there has to be some easy way to do this - can anyone offer some assistance?
Its slow, but you can normally accomplish this with something like 'not in'. (There are other functions in various RDBMS systems to do this in better ways, Oracle for instance has a 'exists' clause that can be used for this.
But you could say:
select id from table1 where id not in (select id from table2)
There are a few ways to do it. Here's one approach using NOT EXISTS:
SELECT userid
FROM table1
WHERE NOT EXISTS
(
SELECT *
FROM table2
WHERE table1.userid = table2.userid
)
And here's another approach using a join:
SELECT table1.userid
FROM table1
LEFT JOIN table2
ON table1.userid = table2.userid
WHERE table2.userid IS NULL
The fastest approach depends on the database.
One way is to use EXCEPT if your TSQL dialect supports it. It is equivalent to performing a left join and null test
SELECT user_id FROM table1 LEFT JOIN table2 ON table1.user_id = table2.user_id WHERE table2.user_id IS NULL;
If it is
SQL Server:
SELECT id FROM table1
EXCEPT
SELECT id FROM table2
Oracle:
SELECT id FROM table1
MINUS
SELECT id FROM table2
Rest: Am not sure....
Try this:
SELECT id FROM table1 WHERE id NOT IN
(
SELECT id FROM table2
)
select ID from table1
where ID not in (select ID from table2)