LEFT JOIN problem within a Stored Procedure - sql

I've an odd problem:
SELECT a.uid, b.*, c.liveId FROM a
INNER JOIN b ON (a.uid=b.uid AND a.versionNo=b.versionNo)
LEFT JOIN c ON (a.uid=c.uid)
WHERE a.memberId=1;
I call that from a query browser and it returns 3 rows. I call it from within a stored procedure and it gives 2 rows (the LEFT JOIN becomes ineffective).
DELIMITER //
DROP PROCEDURE IF EXISTS sp_Test //
CREATE
DEFINER = CURRENT_USER
PROCEDURE sp_Test( IN in_mid INTEGER UNSIGNED )
READS SQL DATA
NOT DETERMINISTIC
BEGIN
SELECT a.uid, b.*, c.liveId FROM a
INNER JOIN b ON (a.uid=b.uid AND a.versionNo=b.versionNo)
LEFT JOIN c ON (a.uid=c.uid)
WHERE a.memberId=in_mid;
END //
DELIMITER ;
I'm stumped! Any suggestions?

Have you forgotten to COMMIT / ROLLBACK one of the sessions after doing an UPDATE / DELETE / INSERT?

I don't have a lot of experience with MySQL, but are there any connection specific settings that would cause NULL comparisons to act differently in each case? For example, if the versionNo could be NULL then one connection might consider NULL = NULL, but the other might evaluate that as false.

I tried it in SQL Server and after a little change it does work for me:
CREATE PROCEDURE sp_Test(
#in_mid int)
AS
BEGIN
SELECT a.uid, b.*, c.liveId FROM a
INNER JOIN b ON (a.uid=b.uid AND a.versionNo=b.versionNo)
LEFT JOIN c ON (a.uid=c.uid)
WHERE a.memberId=#in_mid;
END
Try it.

I've solved it with an utterly bizarre and illogical change.
SELECT a.uid, b.*, c.liveId FROM a
INNER JOIN b ON (a.uid=b.uid AND a.versionNo=b.versionNo)
LEFT JOIN c ON (a.uid=c.uid)
WHERE a.memberId=in_mid
UNION
SELECT a.uid, b.*, c.liveId FROM a
INNER JOIN b ON (a.uid=b.uid AND a.versionNo=b.versionNo)
LEFT JOIN c ON (a.uid=c.uid)
WHERE a.memberId=in_mid;
Doing that within the sproc gives me all the rows that I was getting when executed within the query browser.

Related

How to join Multiple

This is the code example
for three tables and I made a link on them
Now I want to add the age column from table D
SELECT A.COD,a.namee, B.NAMEE,C.NAMEE
FROM ((A INNER JOIN B ON A.COD = B.COD)
LEFT JOIN C ON A.COD = C.COD)
I mean, this code is expected
SELECT A.COD, a.name , B.NAME,C.NAME ,D.Age
FROM ((A INNER JOIN B ON A.COD = B.COD)
LEFT JOIN C ON A.COD = C.COD) , D
But in access, an error message appears, the text of the message says that the JOIN method is not supported
Is there a way to solve this?
Access does not allow to do a direct cross-join (operator ",") involving an SQL expression that includes a different type of join. The solution is as simple as enclosing the first operation between parentheses and add another SELECT, as follows:
SELECT T_A.COD, T_A.Name_ , T_B.Name_, T_C.Name_, T_D.Age
FROM
(
SELECT T_A.COD, T_A.Name_ , T_B.Name_, T_C.Name_
FROM
( T_A
INNER JOIN
T_B
ON T_A.COD = T_B.COD)
LEFT JOIN
T_C
ON T_A.COD = T_C.COD
)
, T_D
My advice is that you always enclose in a SELECT every individual join operation (with the exception of cross-joins) as good programming practice. There is no problem in doing a series of cross-joins because the cross-join operator is associative.

how to perform Two select query in one stored procedure in sql server

I am trying to perform two select query in one stored procedure. But its not giving me any output. There is no error but records are not being displayed.
First I tried this stored Procedure
CREATE PROCEDURE [dbo].[Sp_PriceList_Die_Wise]
#DieNo As Nvarchar(15),
#MetalCode As Int
AS
BEGIN
Select CP.BatchQty,CP.CastingPrice,U.UNITName As 'Unit',MachPrice,U.UNITName As 'M/C Unit' from CustomerPriceList As CP Left Outer Join UNITMaster As U On CP.MUNITID=U.UNITID where MOULDCODE=#DieNo And METALCODE=#MetalCode
SELECT TOP (10) SubOADetail.OANO, SubOADetail.ID, SubOADetail.QTY, SubOADetail.RATE, UNITMaster.UNITName As Unit, OATest.MachPrices, UNITMaster_1.UNITName AS Unit FROM UNITMaster AS UNITMaster_1 RIGHT OUTER JOIN OATest ON UNITMaster_1.UNITID = OATest.MachUnitID RIGHT OUTER JOIN SubOADetail LEFT OUTER JOIN UNITMaster ON SubOADetail.UNIT = UNITMaster.UNITID ON OATest.ID = SubOADetail.ID AND OATest.OANO = SubOADetail.OANO LEFT OUTER JOIN OADetails ON SubOADetail.OANO = OADetails.OANO WHERE SubOADetail.MOULDCODE = #DieNo AND SubOADetail.METALCODE =#MetalCode ORDER BY OADetails.OADATE DESC
END
This gives me output like this
but I want the output in single table so I created this stored procedure
CREATE PROCEDURE [dbo].[Sp_PriceList_Die_Wise]
#DieNo As Nvarchar(15),
#MetalCode As Int
AS
BEGIN
WITH main AS
(
Select CP.BatchQty,CP.CastingPrice,U.UNITName As 'Unit',
MachPrice,U.UNITName As 'M/C Unit' from CustomerPriceList As CP
Left Outer Join UNITMaster As U On CP.MUNITID=U.UNITID
where MOULDCODE=#DieNo And METALCODE=#MetalCode
), sub AS
(
SELECT TOP (10) SubOADetail.OANO, SubOADetail.ID, SubOADetail.QTY, SubOADetail.RATE,
UNITMaster.UNITName As Unit, OATest.MachPrices, UNITMaster_1.UNITName AS MCUnit
FROM UNITMaster AS UNITMaster_1 RIGHT OUTER JOIN OATest ON UNITMaster_1.UNITID = OATest.MachUnitID
RIGHT OUTER JOIN SubOADetail LEFT OUTER JOIN UNITMaster ON SubOADetail.UNIT = UNITMaster.UNITID
ON OATest.ID = SubOADetail.ID AND OATest.OANO = SubOADetail.OANO LEFT OUTER JOIN OADetails
ON SubOADetail.OANO = OADetails.OANO WHERE SubOADetail.MOULDCODE = #DieNo
AND SubOADetail.METALCODE =#MetalCode ORDER BY OADetails.OADATE DESC
)
SELECT *
FROM main m join sub s
ON m.MachPrice = s.MachPrices
END
But this gives me blank record like this
You are using INNER JOIN, and your first table (main) don't have any records, so you will not get any output.
If you want to select from other table even if matching records are not there in the main, you need to change your JOIN to RIGHT JOIN like following.
SELECT *
FROM main m right join sub s
ON m.MachPrice = s.MachPrices
EDIT:
RIGHT JOIN will work for the provided sample data, in case if you have data where left CTE don't have matching records in right CTE or vise versa and you still want to select the records, for such scenario you need a combination of LEFT JOIN and RIGHT JOIN, for this you can use FULL OUTER JOIN like following.
SELECT *
FROM main m full outer join sub s
ON m.MachPrice = s.MachPrices

Conditional join of query using PostgreSQL

I have a case where I need to run different query in join per function variable
Currently I have a function as:
CREATE OR REPLACE FUNCTION a(type_f boolean)
RETURNS SETOF rowtypes AS
$$
declare row rowtypes ;
begin
....
select...
from..
left join (select pp.a, avg(ppp.priceusd) as avgpricetf
from pp
join p on (p.b=pp.b)
join (...) as ppp on (pp.c=p.c)
group by pp.a) tfquery on (tfquery.a=main.a)
....
end;
$$
LANGUAGE plpgsql VOLATILE
This works fine.
I want to modify it so when type_f=True this query will run in the join instad of the original one:
left join (select pp.a,p.d, avg(ppp.priceusd) as avgpricetf
from pp
join p on (p.b=pp.b)
join (...) as ppp on (pp.c=p.c)
group by pp.a,p.d) tfquery on (tfquery.a=main.a and tfquery.d=main.d)
As you can see the query is changed as well as the condition of the join itself.
Basicly:
When type_f=False do:
left join (select pp.a, avg(ppp.priceusd) as avgpricetf
from pp
join p on (p.b=pp.b)
join (...) as ppp on (pp.c=p.c)
group by pp.a) tfquery on (tfquery.a=main.a)
When:
type_f=True do:
left join (select pp.a,p.d, avg(ppp.priceusd) as avgpricetf
from pp
join p on (p.b=pp.b)
join (...) as ppp on (pp.c=p.c)
group by pp.a,p.d) tfquery on (tfquery.a=main.a and tfquery.d=main.d)
How can I do that?
You can use logic like this to kill all possible readability to your query and get expected results:
Select *
from A
left outer join
( select * from B where type_f
union all
select *, A.field from C where not type_f
) X
on X.n = A.n and X.field = A.field
....

join graph disconnect ORACLE

The query below won't run as I have a join graph disconnect. As far as I understand when you alias a table you have to put it first in the join condition, but when i do so I still get the same error, any suggestions?
select
date1.LABEL_YYYY_MM_DD as Some_Label1,
A.Some_Field as Some_Label2,
round(sum(D.Some_Field3)/count (*),0)as Some_Label3
from Table_A A
inner JOIN Table_B B ON (A.some_key = B.some_key)
inner JOIN date_time date1 ON (A.START_DATE_TIME_KEY = date1.DATE_TIME_KEY)
left outer join Table_C C on(C.some_GUID = A.some_ID)
left outer join Table_D D on(D.a_ID = C.a_ID)
where
(1=1)
and date1.LABEL_YYYY_MM_DD ='2015-03-30'
and D.blah ='1'
group by
date1.LABEL_YYYY_MM_DD,
A.Some_Field
order by
date1.LABEL_YYYY_MM_DD
;
Based on my comment above I should change the first inner join to B.some_key = A.some_key and so on however I still get the disconnect...
according to the Oracle documentation (http://docs.oracle.com/javadb/10.8.3.0/ref/rrefsqlj18922.html) there is space required between ON and the boolean expression

SQL query join conditions

I have a query (exert from a stored procedure) that looks something like this:
SELECT S.name
INTO #TempA
from tbl_Student S
INNER JOIN tbl_StudentHSHistory TSHSH on TSHSH.STUD_PK=S.STUD_PK
INNER JOIN tbl_CODETAILS C
on C.CODE_DETL_PK=S.GID
WHERE TSHSH.Begin_date < #BegDate
Here is the issue, the 2nd inner join and corresponding where statement should only happen if only a certain variable (#UseArchive) is true, I don't want it to happen if it is false. Also, in TSHSH certain rows might have no corresponding entries in S. I tried splitting it into 2 separate queries based on #UseArchive but studio refuses to compile that because of the INTO #TempA statement saying that there is already an object named #TempA in the database. Can anyone tell me of a way to fix the query or a way to split the queries with the INTO #TempA statement?
Looks like you're asking 2 questions here.
1- How to fix the SELECT INTO issue:
SELECT INTO only works if the target table does not exist. You need to use INSERT INTO...SELECT if the table already exists.
2- Conditional JOIN:
You'll need to do a LEFT JOIN if the corresponding row may not exist. Try this.
SELECT S.name
FROM tbl_Student S
INNER JOIN tbl_StudentHSHistory TSHSH
ON TSHSH.STUD_PK=S.STUD_PK
LEFT JOIN tbl_CODETAILS C
ON C.CODE_DETL_PK=S.GID
WHERE TSHSH.Begin_date < #BegDate
AND CASE WHEN #UseArchive = 1 THEN c.CODE_DETL_PK ELSE 0 END =
CASE WHEN #UseArchive = 1 THEN S.GID ELSE 0 END
Putting the CASE statement in the WHERE clause and not the JOIN clause will force it to act like an INNER JOIN when #UseArchive and a LEFT JOIN when not.
I'd replace it with LEFT JOIN
LEFT JOIN tbl_CODETAILS C ON #UseArchive = 1 AND C.CODE_DETL_PK=S.GID
You can split the queries and then insert into a temp table easily.
SELECT * INTO #TempA FROM
(
SELECT * FROM Q1
UNION ALL
SELECT * FROM Q2
) T
SELECT S.name
INTO #TempA
from tbl_Student S
INNER JOIN tbl_StudentHSHistory TSHSH
on TSHSH.STUD_PK = S.STUD_PK
INNER JOIN tbl_CODETAILS C
on C.CODE_DETL_PK = S.GID
and #UseArchive = true
WHERE TSHSH.Begin_date < #BegDate
But putting #UseArchive = true in the join in this case is the same as where
Your question does not make much sense to me
So what if TSHSH certain rows might have no corresponding entries in S?
If you want just one of the joins to match
SELECT S.name
INTO #TempA
from tbl_Student S
LEFT OUTER JOIN tbl_StudentHSHistory TSHSH
on TSHSH.STUD_PK = S.STUD_PK
LEFT OUTER JJOIN tbl_CODETAILS C
on C.CODE_DETL_PK = S.GID
and #UseArchive = true
WHERE TSHSH.Begin_date < #BegDate
and ( TSHSH.STUD_PK is not null or C.CODE_DETL_PK id not null )