I have read through a few questions but it did not solve the issue I have with PostgreSql.
I am trying to create a View from multiple table but the following part of the schema returns a "column does not exist" error when it actually does on both column "ContextLink". I do not have the same issue with the other columns though so I am a bit lost when it comes to the solution of this problem.
Postgres returns
ERROR: The column ProjectReferenceDataLibrary_BaseUnit.ContextLink
does not exist
LINE 1218: COALESCE("ProjectReferenceDataLibrary_BaseUnit"."Con...
^
SQL state: 42703
Character: 74151
-- Create link table for class ProjectReferenceDataLibrary
CREATE TABLE "Directory"."ProjectReferenceDataLibrary_BaseUnit" (
"ContextLink" varchar NOT NULL,
"ProjectReferenceDataLibrary" uuid NOT NULL,
"BaseUnit" uuid NOT NULL
);
-- Create link table for class ProjectReferenceDataLibrary
CREATE TABLE "Directory"."ProjectReferenceDataLibrary_BaseQuantityKind" (
"ContextLink" text NOT NULL,
"ProjectReferenceDataLibrary" uuid NOT NULL,
"BaseQuantityKind" uuid NOT NULL,
"OrderKey" bigint NOT NULL
);
CREATE VIEW "Directory"."ProjectReferenceDataLibrary_View" AS
SELECT "ProjectReferenceDataLibrary"."UniqueIdentifier", "ProjectReferenceDataLibrary"."ValueTypeDictionary" AS "ValueTypeSet",
"ProjectReferenceDataLibrary"."Container",
COALESCE("ProjectReferenceDataLibrary_BaseUnit"."BaseUnit",'{}'::text[]) AS "BaseUnit",
COALESCE("ProjectReferenceDataLibrary_BaseUnit"."ContextLink",'{}'::text[]) AS "BaseUnit_ContextLink",
COALESCE("ProjectReferenceDataLibrary_BaseQuantityKind"."BaseQuantityKind",'{}'::text[]) AS "BaseQuantityKind",
COALESCE("ProjectReferenceDataLibrary_BaseQuantityKind"."ContextLink",'{}'::text[]) AS "BaseQuantityKind_ContextLink"
FROM "Directory"."ProjectReferenceDataLibrary" AS "ProjectReferenceDataLibrary"
LEFT JOIN (SELECT "ProjectReferenceDataLibrary" AS "UniqueIdentifier", array_agg("BaseUnit"::text) AS "BaseUnit", array_agg("ContextLink"::text) AS "BaseUnit_ContextLink"
FROM "Directory"."ProjectReferenceDataLibrary_BaseUnit"
JOIN "Directory"."ProjectReferenceDataLibrary" AS "ProjectReferenceDataLibrary" ON "ProjectReferenceDataLibrary" = "UniqueIdentifier"
GROUP BY "ProjectReferenceDataLibrary") AS "ProjectReferenceDataLibrary_BaseUnit" USING ("UniqueIdentifier")
LEFT JOIN (SELECT "ProjectReferenceDataLibrary" AS "UniqueIdentifier", ARRAY[array_agg("OrderKey"::text), array_agg("BaseQuantityKind"::text)] AS "BaseQuantityKind", array_agg("ContextLink"::text) AS "BaseQuantityKind_ContextLink"
FROM "Directory"."ProjectReferenceDataLibrary_BaseQuantityKind"
JOIN "Directory"."ProjectReferenceDataLibrary" AS "ProjectReferenceDataLibrary" ON "ProjectReferenceDataLibrary" = "UniqueIdentifier"
GROUP BY "ProjectReferenceDataLibrary") AS "ProjectReferenceDataLibrary_BaseQuantityKind" USING ("UniqueIdentifier");
I hope I am not missing something silly here.
Thank you greatly in advance for your help.
Cheers,
The column ProjectReferenceDataLibrary_BaseUnit.ContextLink does not exist is correct, at the outer level of your query the base_unit subquery has renamed that column to BaseUnit_ContextLink. So you need to check that every reference you make in that outer layer is using the column aliases of the subqueries.
try this:
CREATE VIEW "Directory"."ProjectReferenceDataLibrary_View" AS
SELECT "ProjectReferenceDataLibrary"."UniqueIdentifier",
"ProjectReferenceDataLibrary"."ValueTypeDictionary" AS "ValueTypeSet",
"ProjectReferenceDataLibrary"."Container",
COALESCE("ProjectReferenceDataLibrary_BaseUnit"."BaseUnit",'{}'::text[]) AS "BaseUnit",
COALESCE("ProjectReferenceDataLibrary_BaseUnit"."BaseUnit_ContextLink",'{}'::text[]) AS "BaseUnit_ContextLink",
COALESCE("ProjectReferenceDataLibrary_BaseQuantityKind"."BaseQuantityKind",'{}'::text[]) AS "BaseQuantityKind",
COALESCE("ProjectReferenceDataLibrary_BaseQuantityKind"."BaseQuantityKind_ContextLink",'{}'::text[]) AS "BaseQuantityKind_ContextLink"
FROM "Directory"."ProjectReferenceDataLibrary" AS "ProjectReferenceDataLibrary"
LEFT JOIN
(
SELECT "ProjectReferenceDataLibrary" AS "UniqueIdentifier",
array_agg("BaseUnit"::text) AS "BaseUnit",
array_agg("ContextLink"::text) AS "BaseUnit_ContextLink"
FROM "Directory"."ProjectReferenceDataLibrary_BaseUnit"
JOIN "Directory"."ProjectReferenceDataLibrary" AS "ProjectReferenceDataLibrary"
ON "ProjectReferenceDataLibrary" = "UniqueIdentifier"
GROUP BY "ProjectReferenceDataLibrary") AS "ProjectReferenceDataLibrary_BaseUnit"
using ("UniqueIdentifier")
LEFT JOIN
(
SELECT "ProjectReferenceDataLibrary" AS "UniqueIdentifier",
array[array_agg("OrderKey"::text), array_agg("BaseQuantityKind"::text)] AS "BaseQuantityKind",
array_agg("ContextLink"::text) AS "BaseQuantityKind_ContextLink"
FROM "Directory"."ProjectReferenceDataLibrary_BaseQuantityKind"
JOIN "Directory"."ProjectReferenceDataLibrary" AS "ProjectReferenceDataLibrary"
ON "ProjectReferenceDataLibrary" = "UniqueIdentifier"
GROUP BY "ProjectReferenceDataLibrary") AS "ProjectReferenceDataLibrary_BaseQuantityKind"
using ("UniqueIdentifier");
Related
I need to insert createdate column twice with two different datatypes one with the datatype defined in the table itself and another in char datatype.
I can insert it by changing the alias name of createdate column but can't insert with same alias name which i need.
so help me out to get correct way of doing it.
My query:
SELECT DISTINCT TE.id, T.debatchqueuelink, TE.transactionlink,
EC.errorclassification, TE.errorvalue,
EC.errorparameter, TE.classificationlink, TE.description,
TE.createdate AS createdate, TO_CHAR(TE.createdate, 'MM/dd/yyyy') AS createdate,
TE.status, TE.rebutt, TE.rebuttedstatus, BQ.appbatchnumber,
BQ.scanbatchnumber, BQ.clientlink, BQ.locationlink, T.patientid,
(DEUD.firstname|| ' ' ||DEUD.lastname) AS deusername, DEUD.email AS deuseremail,
(QCUD.firstname|| ' ' ||QCUD.lastname) AS qcusername, TE.inactive,
TE.decomment
INTO table373
FROM qctransactionerror TE
INNER JOIN errorclassification EC ON EC.id = TE.classificationlink
INNER JOIN qctransaction T ON T.id = TE.transactionlink
INNER JOIN batchqueue BQ ON T.debatchqueuelink = BQ.id
INNER JOIN batchqueue QCBQ ON T.qcbatchqueuelink = QCBQ.id
INNER JOIN userdetail QCUD ON QCBQ.assignedto = QCUD.id
INNER JOIN userdetail DEUD ON BQ.assignedto = DEUD.id
WHERE TE.inactive='t'
AND TE.status IN ('ERROR','QCCORRECTED')
LIMIT 0
The actual error message I am getting is:
Duplicate column:column "createdate" specified more than once
I am trying to run a hive query using COALESCE function to create a view. But it is throwing error like
cannot recognize input near '(' 'SELECT' 'realvalue' in expression specification
The query is given below. Please help and mention what is wrong in this.
CREATE VIEW IF NOT EXISTS exampledb.`ara_service` AS
SELECT T1.EntityId, T1.entityname AS EntityName,
T1.`xxx`,
T1.`yyy`,
COALESCE (T1.`aaa`, (SELECT `realvalue` FROM exampledb.`aba_service`
WHERE `id` = '333')) AS `CombinedValue`,
T1.`ddd`,
T1.`jjj`,
etc..
Please help. The error is in the usage of the select statement inside COALESCE .
NoViableAltException(231#[435:1: precedenceEqualExpression : ( ( LPAREN precedenceBitwiseOrExpression COMMA )=> precedenceEqualExpressionMutiple | precedenceEqualExpressionSingle );])
Thanks
if all you need is a default value, you could do
CREATE VIEW IF NOT EXISTS exampledb.`ara_service` AS
SELECT T1.EntityId, T1.entityname AS EntityName,
T1.`xxx`,
T1.`yyy`,
COALESCE (T1.`aaa`, def.`realvalue` ) AS `CombinedValue`,
T1.`ddd`,
T1.`jjj`,
FROM your_table T1
CROSS JOIN (
SELECT `realvalue`
FROM exampledb.`aba_service` WHERE `id` = '333') def
Suppose I have an activity table and a subscription table. Each activity has an array of generic references to some other object, and each subscription has a single generic reference to some other object in the same set.
CREATE TABLE activity (
id serial primary key,
ob_refs UUID[] not null
);
CREATE TABLE subscription (
id UUID primary key,
ob_ref UUID,
subscribed boolean not null
);
I want to join with the set-returning function unnest so I can find the "deepest" matching subscription, something like this:
SELECT id
FROM (
SELECT DISTINCT ON (activity.id)
activity.id,
x.ob_ref, x.ob_depth,
subscription.subscribed IS NULL OR subscription.subscribed = TRUE
AS subscribed,
FROM activity
LEFT JOIN subscription
ON activity.ob_refs #> array[subscription.ob_ref]
LEFT JOIN unnest(activity.ob_refs)
WITH ORDINALITY AS x(ob_ref, ob_depth)
ON subscription.ob_ref = x.ob_ref
ORDER BY x.ob_depth DESC
) sub
WHERE subscribed = TRUE;
But I can't figure out how to do that second join and get access to the columns. I've tried creating a FromClause like this:
act_ref_t = (sa.select(
[sa.column('unnest', UUID).label('ob_ref'),
sa.column('ordinality', sa.Integer).label('ob_depth')],
from_obj=sa.func.unnest(Activity.ob_refs))
.suffix_with('WITH ORDINALITY')
.alias('act_ref_t'))
...
query = (query
.outerjoin(
act_ref_t,
Subscription.ob_ref == act_ref_t.c.ob_ref))
.order_by(activity.id, act_ref_t.ob_depth)
But that results in this SQL with another subquery:
LEFT OUTER JOIN (
SELECT unnest AS ob_ref, ordinality AS ref_i
FROM unnest(activity.ob_refs) WITH ORDINALITY
) AS act_ref_t
ON subscription.ob_refs #> ARRAY[act_ref_t.ob_ref]
... which fails because of the missing and unsupported LATERAL keyword:
There is an entry for table "activity", but it cannot be referenced from this part of the query.
So, how can I create a JOIN clause for this SRF without using a subquery? Or is there something else I'm missing?
Edit 1 Using sa.text with TextClause.columns instead of sa.select gets me a lot closer:
act_ref_t = (sa.sql.text(
"unnest(activity.ob_refs) WITH ORDINALITY")
.columns(sa.column('unnest', UUID),
sa.column('ordinality', sa.Integer))
.alias('act_ref'))
But the resulting SQL fails because it wraps the clause in parentheses:
LEFT OUTER JOIN (unnest(activity.ob_refs) WITH ORDINALITY)
AS act_ref ON subscription.ob_ref = act_ref.unnest
The error is syntax error at or near ")". Can I get TextAsFrom to not be wrapped in parentheses?
It turns out this is not directly supported by SA, but the correct behaviour can be achieved with a ColumnClause and a FunctionElement. First import this recipe as described by zzzeek in this SA issue. Then create a special unnest function that includes the WITH ORDINALITY modifier:
class unnest_func(ColumnFunction):
name = 'unnest'
column_names = ['unnest', 'ordinality']
#compiles(unnest_func)
def _compile_unnest_func(element, compiler, **kw):
return compiler.visit_function(element, **kw) + " WITH ORDINALITY"
You can then use it in joins, ordering, etc. like this:
act_ref = unnest_func(Activity.ob_refs)
query = (query
.add_columns(act_ref.c.unnest, act_ref.c.ordinality)
.outerjoin(act_ref, sa.true())
.outerjoin(Subscription, Subscription.ob_ref == act_ref.c.unnest)
.order_by(act_ref.c.ordinality.desc()))
For Iseries/IBMi DB2.
I am joining multiple files/tables together.
I have written the code in both DDS and SQL.
The DDS Logical File is working exactly as expected, but I can not use it for embedded sql in rpgle as it then defaults to the SQE engine resulting in horrendous performance.
The SQL view, on the other hand had NULLs until I used IFNULL( MBRDESCR, ''). But now MBRDECSR is a VARCHAR. Which is unacceptable.
So how do I create a SQL join without NULLs and VARCHARs?
Requested Sample Code:
DDS:
JDFTVAL
R TRANSR JFILE(TRANSPF MBRPF)
J JOIN(1 2)
JFLD(MBRID MBRID)
*
TRANSID JREF(1)
MBRID JREF(1)
MBRNAME JREF(2)
MBRSURNME JREF(2)
*
K TRANSID
K MBRID
SQL:
CREATE VIEW TRANSV01 AS (
SELECT TRANSID ,
MBRID ,
CAST(IFNULL(MBRNAME , '') as Char(20)) ,
CAST(IFNULL(MBRSURNME, '') as Char(25))
FROM TRANSPF
--Member Name
LEFT OUTER JOIN MBRPF on MBRID = MBRID
) RCDFMT TRANSR;
Please note the following:
Example above is simplified
Not every MBRID in the TRANSPF has a corresponding entry in the MBRPF (ie. no referential constraint). Thus when MBRPF is joined to the TRANSPF, there will be NULL values in MBRNAME, MBRSURNME. Unless JDFTVAL or IFNULL() is used.
I prefer not to have a VARCHAR, because of performance and extname() in rpgle.
I prefer not to have NULL values, I do not want the pgm to have to handle them.
Assuming it's the 'Allows the null value' that you find undesirable, use a UNION. The first SELECT chooses all the rows that match, which will set the NOT NULL property for you. The second SELECT chooses all the rows that don't have a match - you provide filler fields for those.
CREATE VIEW TRANSV01 AS (
SELECT TRANSID ,
MBRID ,
MBRNAME ,
MBRSURNME
FROM TRANSPF
--Member Name
JOIN MBRPF on MBRID = MBRID
UNION
SELECT TRANSID ,
MBRID ,
CAST('') as Char(20)) ,
CAST('') as Char(25))
FROM TRANSPF
--Member Name
EXCEPTION JOIN MBRPF on MBRID = MBRID
) RCDFMT TRANSR;
SELECT sessions_compare.*
FROM archive_sessions as f_session, sessions_compare
LEFT JOIN archive_sessions as s_session ON (s_session.id = sessions_compare.second_session_id)
LEFT JOIN consols as f_consol ON (f_session.console_id = f_consol.id)
where sessions_compare.first_session_id = f_session.id
after executing a get error like
ERROR: invalid reference to FROM-clause entry for table "f_session"
LINE 13:
LEFT JOIN consols as f_consol ON (f_session.console_id
=...
HINT: There is an entry for table "f_session", but it cannot be referenced from this
part of the query.
When i switch places and have from like sessions_compare, archive_sessions as f_session
i get error like
ERROR: invalid reference to FROM-clause entry for table
"sessions_compare"
LINE 4: ... archive_sessions as s_session ON
(s_session.id = sessions_c...
HINT: There is an entry for table "sessions_compare", but it cannot be
referenced from this part of the query.
And only thing that work is
SELECT sessions_compare.*
FROM sessions_compare
LEFT JOIN archive_sessions as s_session ON (s_session.id = sessions_compare.second_session_id)
,archive_sessions as f_session
LEFT JOIN consols as f_consol ON (f_session.console_id = f_consol.id)
where sessions_compare.first_session_id = f_session.id
And my question is it normal ?? Im young in Postgresql in mysql when using multiple join from tables needed to be in ()
Yes, that's documented behavior in PostgreSQL.
In any case JOIN binds more tightly than the commas separating FROM items.
That means PostgreSQL acts like it builds its working table by evaluating the JOIN clauses before evaluating a comma-list in the FROM clause.
Best practice is generally considered to be to always use JOIN clauses; never put more than one table name in the FROM clause.
Changing the main query to a JOIN (and adding/shortening some correlation names) seems to fix the problem.
DROP SCHEMA fuzz CASCADE;
CREATE SCHEMA fuzz;
SET search_path='fuzz';
create table archive_sessions ( id INTEGER NOT NULL
, console_id INTEGER NOT NULL, game_id INTEGER NOT NULL);
create table sessions_compare (first_session_id INTEGER NOT NULL
, second_session_id INTEGER NOT NULL);
create table consols (id INTEGER NOT NULL);
create table games (id INTEGER NOT NULL);
create table localizations ( consols_id INTEGER NOT NULL, bars_id INTEGER NOT NULL);
create table bars ( id_bars INTEGER NOT NULL, area_id INTEGER NOT NULL);
create table areas ( id_areas INTEGER NOT NULL );
SELECT sco.*
FROM archive_sessions as ase
JOIN sessions_compare sco ON sco.first_session_id = ase.id
LEFT JOIN archive_sessions as ss ON (ss.id = sco.second_session_id)
LEFT JOIN consols as sc ON (ss.console_id = sc.id)
LEFT JOIN games as sg ON (ss.game_id = sg.id)
LEFT JOIN localizations as sl ON (sc.id = sl.consols_id)
LEFT JOIN bars as sb ON (sl.bars_id = sb.id_bars)
LEFT JOIN areas as sa ON (sb.area_id = sa.id_areas)
LEFT JOIN consols as fc ON (ase.console_id = fc.id)
LEFT JOIN games as fg ON (ase.game_id = fg.id)
LEFT JOIN localizations as fl ON (fc.id = fl.consols_id)
LEFT JOIN bars as fb ON (fl.bars_id = fb.id_bars)
LEFT JOIN areas as fa ON (fb.area_id = fa.id_areas)
-- WHERE sco.first_session_id = ase.id
;