how can i combine tables on condition base in postgres functions - postgresql

SELECT status
from orders (CASE WHEN true THEN 'INNER JOIN runningmenus ON orders.runningmenu_id = runningmenus.id' ELSE '' END);
I am getting error near 'CASE', How can i combine table base on condition?

You want to use a join only if a condition is true.
The trick is to always do the join but to use the parameterized condition in the join condition. Fields from both tables will always be included in the output (which is a good thing, the output is clearly defined) but the data may be set or null.
SELECT *
from orders
INNER JOIN runningmenus
ON my_parameter_condition = true AND orders.runningmenu_id = runningmenus.id
Edit : Following #404 comment, the behavior is a bit more complex. You would have to make a left join and keep rows when the parameter condition is false (== no join) or when the joined table has a matching rown (== an inner join):
SELECT *
from orders
LEFT JOIN runningmenus
ON my_parameter_condition = true AND orders.runningmenu_id = runningmenus.id
WHERE (my_parameter_condition = false OR runningmenus.id IS NOT NULL)

Related

Postgresql :joining on fields using CASE expression

I am trying to join two tables on two fields with a below condition
If condition 1 is satisfied then join ON a.field_1 = b.field_1
If condition 2 is satisfied then join ON a.field_2 = b.field_2
In order to do so, I am writing the below query
SELECT
a.field_1,a.field_2,
b.field_1,b.field_2 FROM table a
INNER JOIN table b
CASE WHEN COALESCE(TRIM(a.field_1),'') = '' THEN a.field_1 = b.field_1
ELSE a.field_2 = b.field_2 END
I am not sure whether this would run.
From the manual:
T1 { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2 ON boolean_expression
A JOIN accepts an arbitrary "boolean expression", which may reference columns from both joined relations. While the trivial form is t1.col = t2.col, the boolean expression is not limited to it and so comparing two sets of columns based on some other column is totally fine.
Please note your syntax error #sticky bit pointed out.

How to return an array from a postgres select query?

I have a table that holds scenario information and whether or not it is active and I query the scenario like so
SELECT
scenario.*,
scenario_detail.name,
scenario_detail.is_activated,
scenario_detail.is_current,
scenario_detail.input_values,
scenario_detail.scenario_id,
scenario_detail.user_id,
scenario_detail.plan_id,
scenario_detail.order_index
FROM scenario
INNER join scenario_detail
ON scenario_detail.scenario_id = scenario.id
WHERE scenario_detail.state = 'ACTIVE'
And it returns the scenarios fine.
Now I would like to return an array that will have two items, a list of all activated scenario and another of inactive scenarios.
I know I could slice and sort these scenarios in the front end but I am rather interested in doing it in the backend.
How could I do it?
If all the fields are same then you can use union.
SELECT
scenario.*,
scenario_detail.name,
scenario_detail.is_activated,
scenario_detail.is_current,
scenario_detail.input_values,
scenario_detail.scenario_id,
scenario_detail.user_id,
scenario_detail.plan_id,
scenario_detail.order_index
FROM scenario
INNER join scenario_detail
ON scenario_detail.scenario_id = scenario.id
WHERE scenario_detail.state = 'ACTIVE'
UNION
SELECT
scenario.*,
scenario_detail.name,
scenario_detail.is_activated,
scenario_detail.is_current,
scenario_detail.input_values,
scenario_detail.scenario_id,
scenario_detail.user_id,
scenario_detail.plan_id,
scenario_detail.order_index
FROM scenario
INNER join scenario_detail
ON scenario_detail.scenario_id = scenario.id
WHERE scenario_detail.state = 'INACTIVE'

How does this query populate data?

It is my understanding that when this query runs it would not populate any data any number of times it runs because of the where clause
where c.company_id = lot.company_id
and p.product_id = lot.product_id
and l.packlevel_id = lot.packlevel_id
It looks to me that at the very beginning when the table fact_table_lot is empty the where clause would return with empty data because it would not find anything in an empty table and it would happen everytime. Is my understanding wrong?
insert into fact_table_lot(company_id, product_id, packlevel_id, l_num, sn_count, comm_loct, comm_start, commdate_end, man_date, exp_date, user_id, created_datetime)
select c.company_id, p.product_id, l.packlevel_id, l_num, sn_count, comm_loct, comm_start, commdate_end, man_date, exp_date, user_id, sysdate
from staging_serials s
left outer join fact_table_lot lot on s.lotnumber = lot.l_num
join company c on c.lsc_company_id = s.companyid
join product p on s.compositeprodcode = p.compositeprodcode
join level l on l.unit_of_measure = p.packaginguom
where c.company_id = lot.company_id
and p.product_id = lot.product_id
and l.packlevel_id = lot.packlevel_id
and lot.created_datetime is null
In your query staging_serials s left outer join fact_table_lot lot on s.lotnumber= lot.l_num this will give the result set containing all records from staging_serials and since fact table is empty null values for those column from fact table. If you want no records to be returned use a inner join instead of left join.

T-SQL: Joining on two separate fields based on specific criteria in a query

I have a query in which I am trying to get additional fields from another table through a join field that I manually create. The issue is when the field I create is null, then I want to use another field to join on. I am not sure how to do that without getting duplicate results. I tried a UNION query, but that just displays everything where the values are null when the manually created field value is null. Here is the query:
SELECT
BU = m.BU,
BUFBA = m.BUFBA,
a.CostCenter,
Delegate = m.Delegate,
a.DistrictLookup,
PCOwner = m.PCOwner,
a.PGr,
a.POrg,
PrimaryContact = m.PrimaryContact,
WarehouseManager = m.WarehouseManager,
Zone = m.Zone,
ZoneFBA = m.ZoneFBA
FROM
(SELECT
e.CostCenter,
e.District,
DistrictLookup =
CASE
WHEN e.PGr IN ('N01','BQE','BQA') THEN 'GSS'
WHEN e.PGr = 'BQB' THEN 'BG'
WHEN e.PGr = 'BQF' THEN 'FP'
ELSE e.District
END,
e.PGr,
e.POrg
FROM dbo.E1P e (NOLOCK)
WHERE
e.CoCd = '4433'
) a
LEFT JOIN dbo.Mapping m (NOLOCK) ON m.District = a.DistrictLookup
When the DistrictLookup field is NULL, I need a different join to occur so that the additional fields populate. That join would be:
LEFT JOIN dbo.Mapping m (NOLOCK) ON m.CostCenter = a.CostCenter
How can I write in this second join and not get duplicate results? This is a separate join on different fields and I think it differs from the other methods of doing a conditional join. If it, can someone please explain how to implement that logic into my query?
I believe this is what you are after...
LEFT JOIN dbo.Mapping m (NOLOCK)
ON (a.DistrictLookup IS NOT NULL AND m.District = a.DistrictLookup)
OR (a.DistrictLookup IS NULL AND m.CostCenter = a.CostCenter)

How to use Not Equals in Postgresql Joins

I'm doing this:
select * from schema2."Student" a INNER JOIN
schema1."StudentMapping" b on ( a."StudentID" = b."StudentID")
where a."IsRemoved" = false AND b."IsRemoved" = false
to get only those records from Student table that are present in StudentMapping table, here IsRemoved column I'm using for soft deletion(i.e, whenever any record is to be deleted from any of those tables then only I'm setting it to true, so for IsRemoved = false records are present in the tables) and the query is working fine. Now what I wanted is to get all those records from Student table that are not present in StudentMapping table so I tried this:
select * from schema2."Student" a INNER JOIN
schema1."StudentMapping" b on ( a."StudentId" != b."StudentId")
where a."IsRemoved" = false AND
b."IsRemoved" = false
but this is giving lot of records, more than I expected, what is wrong with this query or is there another way in Postgresql to get all matching recording from one table that are not present in another table.
Do a LEFT OUTER JOIN and then in the where clause, specify to only show recods where the join resulted in a NULL:
select * from schema1."Student" a LEFT OUTER JOIN
schema1."StudentMapping" b on ( a."StudentID" = b."StudentID")
where a."IsRemoved" = false
and b.StudentID IS NULL