PostgreSQL Same Table Left Outer Join With Multiple Tables - postgresql

I have a table which needs to left outer joined with two different tables. When I put the table twice in the query and join it with it self in the where clause (like the sentence below) it works. I think this should not be the correct way. How can I write the select statement and outer join the table with multiple different tables?
SELECT cols."COLUMN_NAME"
, COALESCE(translations."COLUMN_LANG_TITLE",cols."COLUMN_TITLE") AS "COLUMN_TITLE"
, options."OPTION_DESC"
FROM
"EXTAPP_SETUP"."OBJECT_COLUMNS_TAB" cols LEFT OUTER JOIN "EXTAPP_SETUP"."COLUMN_LANG_TITLES_TAB" translations
ON translations."EXTAPP_ID" = cols."EXTAPP_ID" and translations."OBJECT_NAME" = cols."OBJECT_NAME" and translations."COLUMN_NAME" = cols."COLUMN_NAME" and translations."LANGUAGE_CODE" = 'fr',
"EXTAPP_SETUP"."OBJECT_COLUMNS_TAB" cols2 LEFT OUTER JOIN "EXTAPP_SETUP"."COL_FIX_OPTIONS_TAB" options
ON options."EXTAPP_ID" = cols2."EXTAPP_ID" and options."OBJECT_NAME" = cols2."OBJECT_NAME" and options."COLUMN_NAME" = cols2."COLUMN_NAME"
WHERE cols."EXTAPP_ID" = cols2."EXTAPP_ID" and cols."OBJECT_NAME" = cols2."OBJECT_NAME" and cols."COLUMN_NAME" = cols2."COLUMN_NAME"

You can use subsequent left joins.
Since you are not realy using your cols2 table, you can eliminate it from the query. This would also eliminate the where clause, because you don't need to join the cols table with itself
SELECT cols."COLUMN_NAME"
, COALESCE(translations."COLUMN_LANG_TITLE",cols."COLUMN_TITLE") AS "COLUMN_TITLE"
, options."OPTION_DESC"
FROM "EXTAPP_SETUP"."OBJECT_COLUMNS_TAB" cols
LEFT OUTER JOIN "EXTAPP_SETUP"."COLUMN_LANG_TITLES_TAB" translations
ON translations."EXTAPP_ID" = cols."EXTAPP_ID"
and translations."OBJECT_NAME" = cols."OBJECT_NAME"
and translations."COLUMN_NAME" = cols."COLUMN_NAME"
and translations."LANGUAGE_CODE" = 'fr'
LEFT OUTER JOIN "EXTAPP_SETUP"."COL_FIX_OPTIONS_TAB" options
ON options."EXTAPP_ID" = cols."EXTAPP_ID"
and options."OBJECT_NAME" = cols."OBJECT_NAME"
and options."COLUMN_NAME" = cols."COLUMN_NAME"

Related

Creating table from other multiple tables with joins T-SQL

I have a task to do. It's in polish but i will try translate it:
Merge (tables): Towar, KasTow, Notatki (Notatki.tekst replace characters '20' into XC).
so far i merged those tables, but i dont know how to put them into new table.
select *
from towar
left join kastow on towar.towid = kastow.kasaid
left join notatki on kastow.kasaid = notatki.towid
i tried few methods to put this into new table but non of them works.
for example:
select *
into nt
from towar
left join kastow on towar.towid = kastow.kasaid
left join notatki on kastow.kasaid = notatki.towid
and
create table nt
as select *
from towar
left join kastow on towar.towid = kastow.kasaid
left join notatki on kastow.kasaid = notatki.towid

TSQL 2008 How to make columns for views unique

I have a query I am trying to save as a view but SSMS returns an error stating there are multiple columns with the same name.
I have tried to rename the affected columns as an alias but without success.
Column names in each view or function must be unique. Column name 'codemanQuestionID' in view or function 'vwBlocks' is specified more than once.
create view vwBlocks as
SELECT
LUConstructionType.codemanOptionID AS LUConstruction_codemanOptionID
, LUFascias.codemanOptionID AS LUFascias_codemanOptionID
, Block.windowsID
, LUWindows.windows
, LUWindows.codemanQuestionID AS codemanQuestion_ID
, Block.externalDoorID
, LUExternalDoor.externalDoor
, LUExternalDoor.codemanOptionID as LUExternal_codemanOptionID
FROM Block LEFT OUTER JOIN
LUOwnership ON Block.ownershipID = LUOwnership.ownershipID LEFT OUTER JOIN
LULocalAuthority ON Block.localAuthorityID = LULocalAuthority.authorityTypeID LEFT OUTER JOIN
LUConstructionType ON Block.constructionTypeID = LUConstructionType.constructionTypeID LEFT OUTER JOIN
LUTV ON Block.TVID = LUTV.TVID LEFT OUTER JOIN
LUSatellite ON Block.satelliteID = LUSatellite.satelliteID LEFT OUTER JOIN
LUPlayArea ON Block.playArea = LUPlayArea.playAreaID LEFT OUTER JOIN
LURoofCovering ON Block.roofCoveringID = LURoofCovering.roofCoveringID LEFT OUTER JOIN
LUFascias ON Block.fasciasID = LUFascias.fasciasID LEFT OUTER JOIN
LUWindows ON Block.windowsID = LUWindows.windowsID LEFT OUTER JOIN
LUExternalDoor ON Block.externalDoorID = LUExternalDoor.externalDoorID LEFT OUTER JOIN
LUcontractorInfo ON Block.contractorInfoID = LUcontractorInfo.contractorID LEFT OUTER JOIN
LUagentInfo ON Block.agentInfoID = LUagentInfo.agentID LEFT OUTER JOIN
LULandlord ON Block.LandlordID = LULandlord.landlordID LEFT OUTER JOIN
LUblockStatus ON Block.blockStatusID = LUblockStatus.blockStatusID LEFT OUTER JOIN
LUPropertyGroup ON Block.propertyGroup = LUPropertyGroup.propertyGroupID LEFT OUTER JOIN
LUCommunalBoilerType ON Block.communalBoilerType = LUCommunalBoilerType.communalBoilerID LEFT OUTER JOIN
LUExternalAreaManagedBy ON Block.externalAreaManagedBy = LUExternalAreaManagedBy.managedByID LEFT OUTER JOIN
LUgasBoilerMakeModel ON Block.CommBoilerMakeModelID = LUgasBoilerMakeModel.makeModelId LEFT OUTER JOIN
LUMaintenanceResp ON Block.maintenanceRepID = LUMaintenanceResp.maintenanceRepID
Can anybody recommend a solution please?
Thanks for any help in advance.
I'm not seeing codemanQuestionID twice. Here's some advice that has helped me a ton avoid and/or troubleshoot issues like this.
There are at least four ways to alias a column:
(expression) AS ((alias))
((alias)) = (expression)
WITH ((cte name)) ((alias1), (alias2),...
FROM ((subquery)) AS ((alias1>),(alias2,...
AS is the worst IMO. Its sloppy and confusing, especially when you don't include AS. The aliasing style I usually go with is:
SELECT
col1 = <expression>,
col2 = <expression>,
colABC = <expression>
FROM schema.table1 AS t1
JOIN schema.table2 AS t2;
This has made debugging waaay easier.

Why does not adding distinct in this query produce duplicate rows?

This query was taken from a Rails application log...I'm trying to edit a massive postgresql statement I didn't write....If I don't add a distinct keyword after the SELECT, 2 duplicate rows appear for each braintree account. Why is this and is there another way to avoid having to use the distinct to avoid duplicates?
EDIT: I understand what distinct is supposed to do, the reason I'm asking is that it doesn't generate duplicates for other toy lines. By other toy lines, this query is building a "table" for a particular toy id (this specific example toys.id = 12). How do I figure out where the duplicate rows are being generated?
SELECT accounts.braintree_account_id as braintree_account_id,
accounts.braintree_account_id as braintree_account_id, format('%s %s', addresses.first_name,
addresses.last_name) as shipping_address_full_name,
users.email as email, addresses.line_1 as shipping_address_line_1,
addresses.line_2 as shipping_address_line_2, addresses.city as
shipping_address_city, addresses.state as shipping_address_state,
addresses.zip as shipping_address_zip_code, addresses.country
as shipping_address_country, CASE WHEN xy_shirt IS NULL THEN '' ELSE xy_shirt END, plans.name as plan_name, toys.sku as sku, to_char(accounts.created_at, 'MM/DD/YYYY HH24:MM:SS') as
account_created_at,
to_char(accounts.next_assessment_at, 'MM/DD/YYYY HH24:MM:SS') as account_next_assessment_at,
accounts.account_status as account_status FROM \"accounts\" INNER JOIN \"addresses\" ON
\"addresses\".\"id\" = \"accounts\".\"shipping_address_id\" AND \"addresses\".\"type\" IN
('ShippingAddress') LEFT OUTER JOIN shipping_methods ON
shipping_methods.account_id = accounts.id LEFT OUTER JOIN plans ON
accounts.plan_id = plans.id
LEFT OUTER JOIN users ON
accounts.user_id = users.id LEFT OUTER JOIN toys ON plans.toy_id = toys.id
LEFT OUTER JOIN account_variations ON accounts.id =
account_variations.account_id LEFT OUTER JOIN variations ON
account_variations.variation_id = variations.id
LEFT OUTER JOIN
choice_value_variations ON variations.id =
choice_value_variations.variation_id
LEFT OUTER JOIN choice_values ON
choice_value_variations.choice_value_id = choice_values.id LEFT OUTER
JOIN choice_types ON choice_values.choice_type_id = choice_types.id
LEFT
OUTER JOIN choice_type_toys ON choice_type_toys.toy_id = toys.id
AND choice_type_toys.choice_type_id = choice_types.id
LEFT OUTER JOIN
(SELECT * FROM crosstab('SELECT accounts.id, choice_types.id,
choice_values.presentation FROM accounts\n
LEFT JOIN account_variations ON
accounts.id=account_variations.account_id\n
LEFT JOIN variations ON account_variations.variation_id=variations.id\n
LEFT JOIN choice_value_variations ON
variations.id=choice_value_variations.variation_id\n
LEFT JOIN choice_values ON
choice_value_variations.choice_value_id=choice_values.id\n
LEFT JOIN choice_types ON choice_values.choice_type_id=choice_types.id
ORDER BY 1,2',\n 'select distinct choice_types.id
from choice_types JOIN choice_values ON choice_values.choice_type_id =
choice_types.id JOIN choice_value_variations ON
choice_value_variations.choice_value_id = choice_values.id JOIN
variations ON choice_value_variations.variation_id = variations.id JOIN choice_type_toys ON choice_type_toys.choice_type_id = choice_types.id JOIN toys ON toys.id = choice_type_toys.toy_id
where toys.id=12 ORDER
BY choice_types.id ASC')\n
AS (account_id int, xy_shirt
VARCHAR)) account_variation_view\n ON
accounts.id=account_variation_view.account_id WHERE
\"accounts\".\"account_status\" = 'active' AND
\"addresses\".\"flagged_invalid_at\" IS NULL AND \"toys\".\"id\" = 12
AND (NOT EXISTS (SELECT \"account_skipped_months\".* FROM
\"account_skipped_months\" WHERE
\"account_skipped_months\".\"month_year\" = 'JUL2016' AND
(account_skipped_months.account_id = accounts.id)))"
The purpose of using DISTINCT in a SELECT statement is to eliminate duplicate rows.

Linq to SQL self join where right part of join is filtered

I am trying to map a self join where the right table must be filtered, e.g. SQL such as this:
select t2.* from table t
left join table t2
on t2.parentID = t.ID and t2.active=1;
I can figure out the syntax if I wanted to filter the left table:
// works
var query = from t in table
where t.active= 1
join t2 in table
on t.parentID equals t2.ID into joined
from r in joined.DefaultIfEmpty() ...
But I can't figure out how to filter the right table. It seems like it should be something like this...
// does not work
var query = from t in table
join t2 in table
where t.field = 1
on t.parentID equals t2.ID into joined
from r in joined.DefaultIfEmpty() ...
(not valid... join can't have where). There is discussion of using multiple from clauses, but if I create more than one from clause, so I can add a where to the 2nd one, I can't figure out how to join the results of them into a new temporary table.
I can't just add a "where" after the join; the right table must be filtered first or matches will occur, and a where clause at the end would remove the row from the left table that I do want in the output. That is, the output should have rows where there's nothing matched from filtered right table. So I need to filter the right table before the join.
I think you are looking to do this:
var query = from t in table
join t2 in
(from t3 in table
where t3.field = 1
select t3)
on t.parentID equals t2.ID into joined
from r in joined.DefaultIfEmpty() ...
Another way is to use multiple from like this:
var query = from t in table
from t2 in table.Where(x => x.field = 1)
.Where(x => x.ID == t.parentID)
.DefaultIfEmpty()
select ....

select more fields within one select

I manage to do the selection with more selects and a loop. 4 tables ( the last one was just for collecting all the data )
But now i'm thinking of a way to select all the fields i need with just one select statement. Here is the huge select :)
SELECT vbak~vbeln vbak~audat
tvakt~bezei
vbap~posnr vbap~matnr vbap~kwmeng vbap~vrkme
lips~vbeln lips~posnr lips~werks lips~lfimg
vbfa~vbtyp_n
FROM vbak JOIN vbap ON vbak~vbeln = vbap~vbeln
JOIN tvakt ON vbak~auart = tvakt~auart
LEFT JOIN vbfa ON vbfa~vbelv = vbak~vbeln AND vbfa~posnv = vbap~posnr
JOIN lips ON vbfa~vbeln = lips~vbeln AND vbfa~posnn = lips~posnr
INTO TABLE gt_salord
WHERE tvakt~spras = 'EN' AND
vbak~vbeln IN s_vbeln AND
vbak~audat IN s_audat.
The problem is this doesn't work. When i try to activate it throws this error: " Unable to compare with "VBAP~POSNR". A table can be joined with a maximum of one other table using LEFT OUTER JOIN "
If i don't use LEFT JOIN and only JOIN it works but i don't get all what i want. I need to get all the SALES ORDERS even if they don't have a DELIVERY ORDER assigned. Is there a way to do that, or do i really have to split my select?
I have noticed in SAP that it's more efficient to simplify select statements and proceed with LOOP and SELECT SINGLE for table that do not participate in data selection.
In your case data from table VBFA could be fetch after data selection (it is not restricting the amount of data fetched from the DB).
Of course it depends on indexes, application server buffering... but, even though it might be counter-intuitive for SQL experts, keeping select statements not too complex in SAP is best.
Can you try the following selection:
SELECT vbak~vbeln vbak~audat
tvakt~bezei
vbap~posnr vbap~matnr vbap~kwmeng vbap~vrkme
lips~vbeln lips~posnr lips~werks lips~lfimg
vbfa~vbtyp_n
FROM vbak JOIN vbap ON vbak~vbeln = vbap~vbeln
JOIN tvakt ON vbak~auart = tvakt~auart
LEFT JOIN vbfa ON vbfa~vbelv = vbap~vbeln AND vbfa~posnv = vbap~posnr
JOIN lips ON vbfa~vbeln = lips~vbeln AND vbfa~posnn = lips~posnr
INTO TABLE gt_salord
WHERE tvakt~spras = 'EN' AND
vbak~vbeln IN s_vbeln AND
vbak~audat IN s_audat.
I can't test the result, but the syntax check say: ok.
There is only one tiny difference:
x---- difference
v
LEFT JOIN vbfa ON vbfa~vbelv = vbap~vbeln AND vbfa~posnv = vbap~posnr
LEFT JOIN vbfa ON vbfa~vbelv = vbak~vbeln AND vbfa~posnv = vbap~posnr
You compared vbfa~vbelv with vbak~vbeln, I do it with vbap~vbeln. Both have the same value, but in the on-clause you use again vbap.
I dont know about SAP Abap . But from SQL point of view you can use derived query if it is supported in SAP.
here is some approach :
select * from
(
select * from
table1 inner join table2 on table1.key=table2.key
inner join table3 on table1.key=table3.key
) a left outer join table4 b
on a.key=b.key
Posting this as the question is tagged as SQL. Hope it works
Try to change the order of table fields in the on clause of left join. Put vbap~vbeln = vbfa~vbelv