A question about JOIN - sql

I need to do something like this to fill a parts table:
SELECT (CASE t1.part IS NULL THEN t2.part ELSE t1.part END) AS partno,
t3.desc
FROM t1
LEFT JOIN join t2 ON [certain condition]
LEFT JOIN t3 ON t1.part = t3.part
OR t2.part = t3.part
...so this will select the value for partno from t2 in case that part is null in t1, then i need to take the description from t3 but when I run it it takes forever and never return the results, How can I do this faster? if I am missing some details please ask.
this are the tables
alt text http://img15.imageshack.us/img15/3878/74385879.png
this is the actual procedure
DELIMITER $$
DROP PROCEDURE IF EXISTS `getMonthDetail` $$
CREATE DEFINER=`root`#`%` PROCEDURE `getMonthDetail`(fechai Date, wid int)
BEGIN
select distinct
ins.inventoryinid,
(
select group_concat(concat(documents.documentname,': ', inventoryin_documents.documentno))
from inventoryin_documents
left join documents on documents.documentid=inventoryin_documents.documentid
where inventoryin_documents.inventoryinid = docin.inventoryinid
group by inventoryin_documents.inventoryinid
)as docin,
trace.inventoryoutid,
(
select group_concat(concat(documents.documentname,': ', inventoryout_documents.documentno))
from inventoryout_documents
left join documents on documents.documentid=inventoryout_documents.documentid
where inventoryout_documents.inventoryoutid = docout.inventoryoutid
group by inventoryout_documents.inventoryoutid
) as docout,
outs.inventoryoutdate,
(case when trace.partnumberp is null then indetails.partnumberp else trace.partnumberp end) as nopart,
p.descriptionsmall,
trace.quantity
from
inventoryin as ins
left join inventoryinouttrace as trace on trace.inventoryinid = ins.inventoryinid
left join inventoryin_documents as docin on docin.inventoryinid = ins.inventoryinid
left join inventoryout_documents as docout on docout.inventoryoutid = trace.inventoryoutid
left join inventoryout as outs on outs.inventoryoutid = trace.inventoryoutid
left join inventoryindetails indetails on ins.inventoryinid = indetails.inventoryinid
left join product as p on trace.partnumberp=p.partnumberp
where
((ins.inventorydate > fechai+0 and ins.inventorydate < fechai+100)
or (outs.inventoryoutdate > fechai+0 and outs.inventoryoutdate < fechai+100));
END $$
DELIMITER ;
and when I Hit the explain button in the query browser it returns a error...

Try:
SELECT COALESCE(t1.part, t2.part) AS partno,
COALESCE(t3.desc, t4.desc)
FROM t1
LEFT JOIN join t2 ON [certain condition]
LEFT JOIN t3 ON t3.part = t1.part
LEFT JOIN t3 AS t4 ON t4.part = t1.part
OR's are notorious for poor performance.

OR clauses run slow and you should consider replacing them with a UNION which would still utilize any INDEXES you may have on your t1, t2, and t3 tables:
SELECT IFNULL(t1.part, t2.part) AS partno, t3.desc
FROM t1
LEFT JOIN t2 ON (condition here)
LEFT JOIN t3 ON (t1.part = t3.part)
UNION DISTINCT
SELECT IFNULL(t1.part, t2.part) AS partno, t3.desc
FROM t1
LEFT JOIN t2 ON (condition here)
LEFT JOIN t3 ON (t2.part = t3.part)
Also, your CASE() function, much the same as my simplified IFNULL() function, ends up using a temporary table. This is unavoidable when utilizing such functions.

Tell us the actual structure of the data and please show us the EXPLAIN of the query so we can see why it runs slow!
Only a guess: Are there indexes on the right coumns?

Your certain condition should be t2.id=t1.id and have more where clauses in your WHERE statement.
You may want to simplify this down to just have two select statements and see if it is slow, first.
You may be missing an index that would be helpful.
Once the two selects are fine, then you can add in the case command to the sql, and see what is going on, but don't change anything else in your query.
Then, you can give queries and times, which will help people to give a better answer.

Ok for the bleeding obvious : I suppose you have indexed the fields that you use in your joins?

Related

How to simplify to use ISNULL with LEFT OUTER JOIN to merge tables

I need to merge below Table 1 & Table 2 as indicated in "Merge".
The query I wrote below works; but it is TOO SLOW! Is there any simpler way which returns it faster?
SELECT T1.Loc, T2.SO, T2.PO, T1.Item
FROM Table1 T1
LEFT OUTER JOIN Table2 T2
ON ISNULL(T1.[SO2],T1.[SO1]) = T2.[SO]
Never use commas in the FROM clause. Always use proper, explicit JOIN syntax:
SELECT *
FROM Table1 T1 LEFT OUTER JOIN
Table2 T2
ON COALESCE(T1.[SO2], T1.[SO1]) = T2.[SO];
There is no need to join to Table2 twice (much less getting a Cartesian product). I prefer COALESCE() to ISNULL() simply because the former is the ANSI standard function for replacing NULL values.
I should add that for performance, two joins might be preferable:
SELECT T1.Loc, COALESCE(T2_2.SO, T2_1.SO) as SO,
COALESCE(T2_2.PO, T2_1.PO) as PO, T1.Item
FROM Table1 T1 LEFT OUTER JOIN
Table2 T2_2
ON T1.[SO2] = T2_2.[SO] LEFT OUTER JOIN
Table2 T2_1
ON T1.[SO1] = T2_1.[SO] AND T1.[SO2] IS NULL;
It is easier for the SQL engine to optimize joins that use only equality and AND conditions, on the clean column references (that is, the columns are not the arguments to any function calls).
Hope this SQL full fill your requirement.
Select T2.Loc, T2.SO, T2.PO, T1.item from table 2 T2 join table1 T1
on T1.SO1 = T2.SO;

Oracle join tables with multiple conditions

I ve post a pic of what im trying to accomplish ive been trying all the codes i can find online but nothing seems to work.
here a snippet of the code i'm trying to use.. Am i even on the right track? PS. its an oracle DB
SELECT
q1.x, q1.y, q2.z, ...
FROM
(SELECT ... FROM ...) q1
LEFT JOIN
(SELECT ... FROM ...) q2
ON q1.column = q2.column
thank you for help!
Unless I'm missing something profound, this is just two joins:
select t1.*, t2a.text as text1, t2a.text as text2
from t1 join
t2 t2a
on t2a.num = t1.num1 join
t2 t2b
on t2b.num = t1.num2;
You need to join Table 2 twice, once on Table1.NUM1 and once on Table1.NUM2:
SELECT
t1.A, t1.NUM1, t1.NUM2, t2a.TEXT AS TEXT1, t2b.TEXT AS TEXT2
FROM
Table1 t1
INNER JOIN Table2 t2a
ON t1.NUM1 = t2a.NUM
INNER JOIN Table2 t2b
ON t1.NUM2 = t2b.NUM
You can also use LEFT JOINS, if rows from Table 2 are missing and you still want to include the rows of Table 1 in such cases.
In order to be able to identify the 2 instances of Table 2 you need to give them different aliases. The alias on Table 1 is just for convenience.

Optimization of DB2 query which uses joins and takes 1.5 hours to execute

when i run SELECT stataement on my view it takes around 1.5 hours to run, what can i do to optimize it.
Below is the sample structure of how my view looks like
CREATE VIEW SCHEMANAME.VIEWNAME
{
COL, COL1, COL2, COL3 }
AS SELECT
COST.ETA,
CASE
WHEN VOL.CURR IS NOT NULL
THEN COALESCE {VOL.COMM,0}
END CASE,
CASE
WHEN...
END CASE
FROM TABLE1 t1 inner join TABLE2 t2 ON t1.ETA=t2.ETA
INNER JOIN TABLE3 t3 on t2.ETA=t3.ETA
LEFT OUTER JOIN TABLE4 t4 on t2.ETA=t4.ETA
This is your query:
SELECT COST.ETA,
(CASE WHEN VOL.CURR IS NOT NULL THEN COALESCE {VOL.COMM,0}
END) as ??,
. . .
FROM TABLE1 t1 inner join
TABLE2 t2
ON t1.ETA = t2.ETA INNER JOIN
TABLE3 t3
on t2.ETA = t3.ETA LEFT OUTER JOIN
TABLE4 t4
on t2.ETA = t4.ETA;
First, I will the fact that the select clause references tables that are not in the from clause. I assume this is a typo.
Second, you should be able to use indexes to improve this query: table1(eta), table2(eta),table3(eta), andtable4(eta).
Third, I am highly suspicious on seeing the same column used for joining so many tables. I suspect that you might have cartesian products occurring, because there are multiple values of any given eta in several tables. If that is the case, you need to fix the query to better reflect what you really need. If so, ask another question with sample data and desired results, because your query is probably not correct.

unable to convert SQL query to Linq

Please help me try and convert this join query. I am trying to convert the following SQL query into a LINQ query, but can not get it working. Can any one help me solve this?
SELECT T1.BoCode, case when T2.qty is null then 0 else T2.qty end
FROM
(SELECT bocode from TABLE1) as T1
left join
(SELECT cBoCode, sum(qty) as qty FROM TABLE2 where ncampnurn in
(select nurn FROM TABLE3 INNER JOIN TABLE4 ON TABLE3.CampaignCode =
TABLE4.CampaignCode
where TABLE3.Month = 'Sep12' and TABLE4.ReportGroup = 'testgroup' )
GROUP BY cBoCode) as T2
ON T1.BoCode = T2.cBoCode
order by T1.BoCode
I have only been able to do the middle bit and then get stuck on whether I need to use Contains or Any.
from t3 in table3
join t4 in table4 on t3.CampaignCode equals t4.CampaignCode
where t3.Month == "Sep12" && t4.ReportGroup == "testgroup"
select t3.Nurn
refer this
SQL to LINQ Tool
or by doing it by yourself
http://www.linqpad.net/

Where Exists query returning incorrect results

The inner query here returns values that only appear in one of the tables. The outer query is supposed to return a count of those. Instead, it returns the entire table, not just the NULL values.
select count(*) from tblicd
where exists
(
select i.icd_id
from tblicd i left outer join icd_jxn on icd_jxn.icd_id=i.icd_id
where icd_jxn.icd_id is null
)
The inner query
select i.icd_id
from tblicd i left outer join icd_jxn on icd_jxn.icd_id=i.icd_id
where icd_jxn.icd_id is null
works and does what I want. I'd like (using a sub query method like this) to use the outer query to just return the number of rows that the inner query returns.
You need to join the two (outer and inner) tblicd tables in the subquery:
and i.icd_id = tblicd.icd_id
(or whatever the id of the tblicd table is)
The query you posted doesn't make any sense. However, from your description, it sounds like you've got two tables and you're trying to find any IDs that don't exist in both tables. If that's correct, you should try something like this:
select count(*) as cnt
from table1 t1
full outer join
table2 t2
on t1.id = t2.id
where t1.id is null
or t2.id is null
This may not work in the database you're using, but since you didn't tell us that, we can't tailor the solution to fit your dialect of SQL.
Based on the revised question, you could simplify this a number of ways:
select count(*)
from tblicd
where not exists (select i.icd_id
from icd_jxn
where icd_jxn.icd_id = tblicd)
select count(tblicd.icd_id)
from tblicd
left join
icd_jxn
on tblicd.icd_id = icd_jxn.icd_id
where icd_jxn.icd_id is null
select count(tblicd.icd_id)
from tblicd
where icd_id not in (select icd_id
from icd_jxn)
Basically, there's no reason to select from tblicd twice.