Conditional join of query using PostgreSQL - sql

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
....

Related

SQL Query Select from 1 table and return data based on 2 columns

I'm working on a SQL query where I have data stored in table r. Based on the columns of give or receive, I need to store the data in a temp table to then store in a new table.
Essentially, the data is pulling from 3 tables and the end goal is to get the binary code for an image and store to display in .net
I'm trying to figure out the multi select at this time
So give or receive in r equals Username in S, display all the data that pertains and get the image if employee equals employee
I've tried a good amount of code and I feel like an OR would do the trick but it doesn't seem to.
Thanks for any help you may provide.
SELECT
r.id, r.give, r.[receive], r.[type], r.[description], r.isApproved,
r.photoGive, r.photoReceive
INTO
#temp2
FROM
Intranet.dbo.Recgonize r
SELECT s.Employee, s.Username
INTO #temp3
FROM Vision7.dbo.SEUser s
SELECT p.Photo, p.Employee
INTO #temp4
FROM Vision7.dbo.EMPhoto p
SELECT *
FROM #temp2 AS a
INNER JOIN #temp3 b ON a.give = b.Username
INNER JOIN #temp4 c ON b.Employee = c.Employee
DROP TABLE #temp2
DROP TABLE #temp3
DROP TABLE #temp4
Why are you using temporary tables for this? These just make code harder to debug and maintain, more expensive to run, and more complicated to understand.
JOINs will work without temporary tables. But you do have to additional logic to get the give and receive values in separate columns, so more JOINs are necessary:
SELECT r.id, r.give, r.[receive], r.[type], r.[description],
r.isApproved, r.photoGive, r.photoReceive,
pg.Photo as give_photo, pg.Employee as give_employee,
pr.Photo as receive_photo, pr.Employee as receive_employee
FROM Intranet.dbo.Recognize r LEFT JOIN
Vision7.dbo.SEUser sg
ON r.give = sg.Username LEFT JOIN
Vision7.dbo.SEUser sr
ON r.receive = sr.Username LEFT JOIN
Vision7.dbo.EMPhoto pg
ON sg.Employee = pg.Employee LEFT JOIN
Vision7.dbo.EMPhoto pr
ON sr.Employee = pr.Employee
Try with a single script as below-
SELECT a.id,
a.give,
a.[receive],
a.[type],
a.[description],
a.isApproved,
a.photoGive,
a.photoReceive,
b.Employee,
b.Username,
c.Photo,
c.Employee
FROM Intranet.dbo.Recgonize A
INNER JOIN Vision7.dbo.SEUser B ON a.give = b.Username
INNER JOIN Vision7.dbo.EMPhoto C ON b.Employee = c.Employee;
You may want try following:
-- Include only required columns select rather than "*"
SELECT *
FROM #temp2 AS a
INNER JOIN #temp3 b ON a.give = b.Username
INNER JOIN #temp3 b2 ON a.receive = b2.Username
INNER JOIN #temp4 c ON b.Employee = c.Employee
INNER JOIN #temp4 c2 ON b2.Employee = c2.Employee
or
-- Include only required columns in select rather than "*"
SELECT *
FROM
(select r.id, r.give as UserName, r.[type], r.[description], r.isApproved, r.photoGive from #temp2
union
select r.id, r.[receive], r.[type], r.[description], r.isApproved, r.photoReceive from #temp2
) AS a
INNER JOIN #temp3 b ON a.UserName = b.Username
INNER JOIN #temp4 c ON b.Employee = c.Employee
If temp tables are NOT used for necessary need by application, same logic can work with actual tables, just replace #Temp2, #Temp3, #Temp4 with appropriate table names.

SQL Selecting rows with not the same condition for all

I have to create SQL query that select persons datas. Every person has several grades and I have to select first by time for everyone. I don't know how do it because conditional is different for every person. Below is my current code which doesn't works.
SELECT s.sol_last_name,
g.grade_name,
MIN(sg.sol_grade_date_from)
FROM [dbo].[dim_s####] AS s
LEFT JOIN [dbo].[fact_s####_grade] AS sg ON s.sol_key = sg.sol_grade_sollers_key
LEFT JOIN [dbo].[dim_grade] AS g ON g.grade_key = sg.sol_grade_grade_key
GROUP BY s.sol_last_name,
g.grade_name
HAVING MIN(sg.sol_grade_date_from) = sg.sol_grade_date_from
You can put the earliest date in a subquery, and then inner join there:
SELECT s.sol_last_name,
g.grade_name,
sg.sol_grade_date_from
FROM [dbo].[dim_s####] AS s
INNER JOIN (
select sol_grade_grade_key
,min(sol_grade_date_from) as sol_grade_date_
from from [dbo].[dim_grade]
GROUP BY sol_grade_grade_key) AS g
ON g.grade_key = sg.sol_grade_grade_key
LEFT JOIN [dbo].[fact_s####_grade] AS sg
ON s.sol_key = sg.sol_grade_sollers_key
Use a Common Table Expression (cte) to save some typing. Then do a NOT EXISTS to return a row only if same sol_last_name has no older grade.
WITH CTE (sol_last_name, grade_name, grade_date_from) AS
(
SELECT s.sol_last_name,
g.grade_name,
sg.sol_grade_date_from
FROM [dbo].[dim_s####] AS s
LEFT JOIN [dbo].[fact_s####_grade] AS sg ON s.sol_key = sg.sol_grade_sollers_key
LEFT JOIN [dbo].[dim_grade] AS g ON g.grade_key = sg.sol_grade_grade_key
)
select sol_last_name, grade_name, grade_date_from
from cte as t1
where not exists (select 1 from cte t2
where t2.sol_last_name = t1.sol_last_name
and t2.grade_date_from < t2.grade_date_from)

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

How to write subquery inside the OUTER JOIN Statement

I want to join two table CUSTMR and DEPRMNT.
My needed is: LEFT OUTER JOIN OF two or more Tables with subquery inside the LEFT OUTER JOIN as shown below:
Table: CUSTMR , DEPRMNT
Query as:
SELECT
cs.CUSID
,dp.DEPID
FROM
CUSTMR cs
LEFT OUTER JOIN (
SELECT
dp.DEPID
,dp.DEPNAME
FROM
DEPRMNT dp
WHERE
dp.DEPADDRESS = 'TOKYO'
)
ON (
dp.DEPID = cs.CUSID
AND cs.CUSTNAME = dp.DEPNAME
)
WHERE
cs.CUSID != ''
Here the subquery is:
SELECT
dp.DEPID, dp.DEPNAME
FROM
DEPRMNT dp
WHERE
dp.DEPADDRESS = 'TOKYO'
Is it possible to write such subquery inside LEFT OUTER JOIN?
I am getting an error when running this query on my DB2 database.
You need the "correlation id" (the "AS SS" thingy) on the sub-select to reference the fields in the "ON" condition. The id's assigned inside the sub select are not usable in the join.
SELECT
cs.CUSID
,dp.DEPID
FROM
CUSTMR cs
LEFT OUTER JOIN (
SELECT
DEPID
,DEPNAME
FROM
DEPRMNT
WHERE
dp.DEPADDRESS = 'TOKYO'
) ss
ON (
ss.DEPID = cs.CUSID
AND ss.DEPNAME = cs.CUSTNAME
)
WHERE
cs.CUSID != ''
I think you don't have to use sub query in this scenario.You can directly left outer join the DEPRMNT table .
While using Left Outer Join ,don't use columns in the RHS table of the join in the where condition, you ll get wrong output

LEFT JOIN problem within a Stored Procedure

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.