LEFt JOIN LATERAL showing error with SELECT - sql

I am trying to run below query :
SELECT
tc.ID_NUMBER AS AFC_RPP_Number,
hc.BUSINESS AS Business,
hc.DIRECTOR AS Director,
tc.REASON_FOR_REVISION AS Description_of_Change
FROM alo_gg.AWS_PIM tc
left join lateral(
select BUSINESS,DIRECTOR
FROM alo_ggg.tracker
WHERE START_DATE <= tc.DATE AND SO = tc.SO
ORDER BY START_DATE DESC
LIMIT 1
) hc;
Above query is showing error:
ERROR: syntax error at or near "SELECT"
left join lateral (SELECT BUSINESS,DIRECTOR...
If I run the subquery separately it is giving me a result, but with lateral it is giving me an error.

You need to add ON TRUE and remove comma:
SELECT
tc.ID_NUMBER AS AFC_RPP_Number,
hc.BUSINESS AS Business,
hc.DIRECTOR AS Director,
tc.REASON_FOR_REVISION AS Description_of_Change
FROM alo_gg.AWS_PIM tc -- removing comma
left join lateral(
select BUSINESS,DIRECTOR
FROM alo_ggg.tracker
WHERE START_DATE <= tc.DATE AND SO = tc.SO
ORDER BY START_DATE DESC
LIMIT 1
) hc ON TRUE; -- adding `ON` clause

Related

Syntax error to combine left join and select

I'm getting a syntax error at Left Join. So in trying to combine the two, i used the left join and the brackets. I'm not sure where the problem is:
SELECT DISTINCT a.order_id
FROM fact.outbound AS a
ORDER BY Rand()
LIMIT 5
LEFT JOIN (
SELECT
outbound.marketplace_name,
outbound.product_type,
outbound.mpid,
outbound.order_id,
outbound.sku,
pbdh.mpid,
pbdh.product_type,
pbdh.validated_exp_reach,
pbdh.ultimate_sales_rank_de,
pbdh.ultimate_sales_rank_fr,
(
pbdh.very_good_stock_count + good_stock_count + new_Stock_count
) as total_stock
FROM
fact.outbound AS outbound
LEFT JOIN reporting_layer.pricing_bi_data_historisation AS pbdh ON outbound.mpid = pbdh.mpid
AND trunc(outbound.ordered_date) = trunc(pbdh.importdate)
WHERE
outbound.ordered_date > '2022-01-01'
AND pbdh.importdate > '2022-01-01'
LIMIT
5
) AS b ON a.orderid = b.order_id
Error:
You have an error in your SQL syntax; it seems the error is around: 'LEFT JOIN ( SELECT outbound.marketplace_name, outbound.product_t' at line 9
What could be the reason?
Place the first limit logic into a separate subquery, and then join the two subqueries:
SELECT DISTINCT a.order_id
FROM
(
SELECT order_id
FROM fact.outbound
ORDER BY Rand()
LIMIT 5
) a
LEFT JOIN
(
SELECT
outbound.marketplace_name,
outbound.product_type,
outbound.mpid,
outbound.order_id,
outbound.sku,
pbdh.mpid,
pbdh.product_type,
pbdh.validated_exp_reach,
pbdh.ultimate_sales_rank_de,
pbdh.ultimate_sales_rank_fr,
(pbdh.very_good_stock_count +
good_stock_count + new_Stock_count) AS total_stock
FROM fact.outbound AS outbound
LEFT JOIN reporting_layer.pricing_bi_data_historisation AS pbdh
ON outbound.mpid = pbdh.mpid AND
TRUNC(outbound.ordered_date) = TRUNC(pbdh.importdate)
WHERE outbound.ordered_date > '2022-01-01' AND
pbdh.importdate > '2022-01-01'
-- there should be an ORDER BY clause here...
LIMIT 5
) AS b
ON a.orderid = b.order_id;
Note that the select clause of the b subquery can be reduced to just the order_id, as no values from this subquery are actually selected in the end.
You can skip the LEFT JOIN, since no b columns are selected. (And SELECT DISTINCT makes sure any duplicates are eliminated.)
SELECT DISTINCT order_id
FROM fact.outbound
ORDER BY Rand()
LIMIT 5

must appear in the group by clause in sql

I have a sql statement and I am trying to add order by, when I add order statement I get an error
ERROR: column "items.id" must appear in the GROUP BY clause or be used in an aggregate function
My query is.
WITH "has_children_cte"
AS (SELECT DISTINCT "parent_id" AS "item_id",
1 AS "has_children"
FROM "items")
SELECT "item_category_id",
Count(*) AS "count"
FROM "items"
INNER JOIN "items" AS "root_item"
ON ( "root_item"."id" = "items"."root_id" )
LEFT JOIN "item_types"
ON ( "items"."item_type_id" = "item_types"."id" )
LEFT JOIN "item_categories"
ON ( "item_categories"."id" = "item_types"."item_category_id" )
INNER JOIN "order_items"
ON ( "items"."order_item_id" = "order_items"."id" )
INNER JOIN "orders"
ON ( "order_items"."order_id" = "orders"."id" )
LEFT JOIN "has_children_cte"
ON ( "items"."id" = "has_children_cte"."item_id" )
WHERE ( ( "items"."parent_id" IS NULL )
AND ( "items"."state" != 'discarded' ) )
GROUP BY "item_category_id"
ORDER BY "items"."id";
I have add the ORDER BY "items"."id";
Then I get this error. When I try to add items.id into group by I got bad results.
Unfortunately I am unable to handle this error.
The ORDER BY (logically) takes place after the aggregation. And after the aggregation, "items"."id" is not available in each row.
So just use an aggregation function:
ORDER BY MIN("items"."id")

How to join table to table created from query

I query to get the top 5 results of IPs and then i want to get for each IP, the countries and others fields related to it by join.
select actual_ip, actual_country_code, actual_country_name, organization FROM "public"."bus_request" inner join (
select top 5 actual_ip, count(*) FROM "public"."bus_request"
where app_name = 'xxxxx' and request_score>0 and date >= '2019-06-07' and event_type <> 'browser_js'
group by actual_ip order by count desc ) as temp on actual_ip = temp.actual_ip
SQL Error [500310] [42702]: [Amazon](500310) Invalid operation: column reference "actual_ip" is ambiguous;
Not sure exactly which DBMS you're using, but try resolving the ambiguity by specifying the table, e.g.:
select busreq.actual_ip, actual_country_code, actual_country_name, organization FROM "public"."bus_request" as busreq inner join (
select top 5 actual_ip, count(*) FROM "public"."bus_request"
where app_name = 'xxxxx' and request_score>0 and date >= '2019-06-07' and event_type <> 'browser_js'
group by actual_ip order by count desc ) as temp on busreq.actual_ip = temp.actual_ip
(you may need to disambiguate the inner use of actual_ip - but hopefully not.)
You should always qualify all column references in a query that references more than one table. In addition, you should use table aliases so the query is easier to write and to read:
select br.actual_ip, br.actual_country_code, br.actual_country_name, br.organization
from "public"."bus_request" br inner join
(select top 5 br2.actual_ip, count(*)
from "public"."bus_request" br2
where br2.app_name = 'xxxxx' and
br2.request_score > 0 and
br2.date >= '2019-06-07' and
br2.event_type <> 'browser_js'
group by br2.actual_ip
order by count(*) desc
) br2
on br2.actual_ip = br.actual_ip;

Query error IN GROUP BY

I want only one F_LATPRIMI, F_LONPRIMI from any I_ID_NAVE
select I_ID_NAVE ,F_LATPRIMI ,F_LONPRIMI
from(
select
distinct imo,[N_ident_seguenziale]
from
navi
inner join
[ESTERNALIZZAZIONE_FASCICOLINAVE]
ON
[ESTERNALIZZAZIONE_FASCICOLINAVE].[I_ID_NAVE]=navi.[N_ident_seguenziale]
) as tabimo
inner join
posizioni
on
posizioni.[I_ID_NAVE]=tabimo.[N_ident_seguenziale]
where
DATEDIFF(minute, D_TS,GETDATE() )<30
group by I_ID_NAVE
The error is
Msg 8120, Level 16, State 1, Line 3 Column 'posizioni.F_LATPRIMI' is
invalid in the select list because it is not contained in either an
aggregate function or the GROUP BY clause.
I think what you are looking for is not GROUP BY rather ROW_NUMBER() function like
select I_ID_NAVE,
F_LATPRIMI ,
F_LONPRIMI
from (
select
imo,[N_ident_seguenziale], I_ID_NAVE,
F_LATPRIMI ,F_LONPRIMI,
ROW_NUMBER() OVER(PARTITION BY I_ID_NAVE ORDER BY I_ID_NAVE) AS rn
from
navi inner join [ESTERNALIZZAZIONE_FASCICOLINAVE]
ON [ESTERNALIZZAZIONE_FASCICOLINAVE].[I_ID_NAVE] = navi.[N_ident_seguenziale]) tabimo
join posizioni p on p.[I_ID_NAVE] = tabimo.[N_ident_seguenziale]
where DATEDIFF(minute, D_TS,GETDATE() ) < 30
and rn = 1;
One should group by all the columns which is in the select clause...
select I_ID_NAVE ,F_LATPRIMI ,F_LONPRIMI
from(
select
distinct imo,[N_ident_seguenziale]
from
navi
inner join
[ESTERNALIZZAZIONE_FASCICOLINAVE]
ON
[ESTERNALIZZAZIONE_FASCICOLINAVE].[I_ID_NAVE]=navi.[N_ident_seguenziale]
) as tabimo
inner join
posizioni
on
posizioni.[I_ID_NAVE]=tabimo.[N_ident_seguenziale]
where
DATEDIFF(minute, D_TS,GETDATE() )<30
group by I_ID_NAVE,F_LATPRIMI ,F_LONPRIMI
in MsSql when using an Group By, all other columns need to be in an aggregate function (like MAX(), etc).
So maybe what you want is to delete the last row group by I_ID_NAVE.
What do you really want?
Please explain to us so we can help
If you "want the last F_LATPRIMI and F_LONPRIMI from anyI_ID_NAVE"
use the "Last"-Aggregate-function:
select I_ID_NAVE ,LAST(F_LATPRIMI) ,LAST(F_LONPRIMI)
from(
select
distinct imo,[N_ident_seguenziale]
from
navi
inner join
[ESTERNALIZZAZIONE_FASCICOLINAVE]
ON
[ESTERNALIZZAZIONE_FASCICOLINAVE].[I_ID_NAVE]=navi.[N_ident_seguenziale]
) as tabimo
inner join
posizioni
on
posizioni.[I_ID_NAVE]=tabimo.[N_ident_seguenziale]
where
DATEDIFF(minute, D_TS,GETDATE() )<30
group by I_ID_NAVE

Limit join to one row

I have the following query:
SELECT sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount, 'rma' as
"creditType", "Clients"."company" as "client", "Clients".id as "ClientId", "Rmas".*
FROM "Rmas" JOIN "EsnsRmas" on("EsnsRmas"."RmaId" = "Rmas"."id")
JOIN "Esns" on ("Esns".id = "EsnsRmas"."EsnId")
JOIN "EsnsSalesOrderItems" on("EsnsSalesOrderItems"."EsnId" = "Esns"."id" )
JOIN "SalesOrderItems" on("SalesOrderItems"."id" = "EsnsSalesOrderItems"."SalesOrderItemId")
JOIN "Clients" on("Clients"."id" = "Rmas"."ClientId" )
WHERE "Rmas"."credited"=false AND "Rmas"."verifyStatus" IS NOT null
GROUP BY "Clients".id, "Rmas".id;
The problem is that the table "EsnsSalesOrderItems" can have the same EsnId in different entries. I want to restrict the query to only pull the last entry in "EsnsSalesOrderItems" that has the same "EsnId".
By "last" entry I mean the following:
The one that appears last in the table "EsnsSalesOrderItems". So for example if "EsnsSalesOrderItems" has two entries with "EsnId" = 6 and "createdAt" = '2012-06-19' and '2012-07-19' respectively it should only give me the entry from '2012-07-19'.
SELECT (count(*) * sum(s."price")) AS amount
, 'rma' AS "creditType"
, c."company" AS "client"
, c.id AS "ClientId"
, r.*
FROM "Rmas" r
JOIN "EsnsRmas" er ON er."RmaId" = r."id"
JOIN "Esns" e ON e.id = er."EsnId"
JOIN (
SELECT DISTINCT ON ("EsnId") *
FROM "EsnsSalesOrderItems"
ORDER BY "EsnId", "createdAt" DESC
) es ON es."EsnId" = e."id"
JOIN "SalesOrderItems" s ON s."id" = es."SalesOrderItemId"
JOIN "Clients" c ON c."id" = r."ClientId"
WHERE r."credited" = FALSE
AND r."verifyStatus" IS NOT NULL
GROUP BY c.id, r.id;
Your query in the question has an illegal aggregate over another aggregate:
sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount
Simplified and converted to legal syntax:
(count(*) * sum(s."price")) AS amount
But do you really want to multiply with the count per group?
I retrieve the the single row per group in "EsnsSalesOrderItems" with DISTINCT ON. Detailed explanation:
Select first row in each GROUP BY group?
I also added table aliases and formatting to make the query easier to parse for human eyes. If you could avoid camel case you could get rid of all the double quotes clouding the view.
Something like:
join (
select "EsnId",
row_number() over (partition by "EsnId" order by "createdAt" desc) as rn
from "EsnsSalesOrderItems"
) t ON t."EsnId" = "Esns"."id" and rn = 1
this will select the latest "EsnId" from "EsnsSalesOrderItems" based on the column creation_date. As you didn't post the structure of your tables, I had to "invent" a column name. You can use any column that allows you to define an order on the rows that suits you.
But remember the concept of the "last row" is only valid if you specifiy an order or the rows. A table as such is not ordered, nor is the result of a query unless you specify an order by
Necromancing because the answers are outdated.
Take advantage of the LATERAL keyword introduced in PG 9.3
left | right | inner JOIN LATERAL
I'll explain with an example:
Assuming you have a table "Contacts".
Now contacts have organisational units.
They can have one OU at a point in time, but N OUs at N points in time.
Now, if you have to query contacts and OU in a time period (not a reporting date, but a date range), you could N-fold increase the record count if you just did a left join.
So, to display the OU, you need to just join the first OU for each contact (where what shall be first is an arbitrary criterion - when taking the last value, for example, that is just another way of saying the first value when sorted by descending date order).
In SQL-server, you would use cross-apply (or rather OUTER APPLY since we need a left join), which will invoke a table-valued function on each row it has to join.
SELECT * FROM T_Contacts
--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989
-- CROSS APPLY -- = INNER JOIN
OUTER APPLY -- = LEFT JOIN
(
SELECT TOP 1
--MAP_CTCOU_UID
MAP_CTCOU_CT_UID
,MAP_CTCOU_COU_UID
,MAP_CTCOU_DateFrom
,MAP_CTCOU_DateTo
FROM T_MAP_Contacts_Ref_OrganisationalUnit
WHERE MAP_CTCOU_SoftDeleteStatus = 1
AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID
/*
AND
(
(#in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo)
AND
(#in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom)
)
*/
ORDER BY MAP_CTCOU_DateFrom
) AS FirstOE
In PostgreSQL, starting from version 9.3, you can do that, too - just use the LATERAL keyword to achieve the same:
SELECT * FROM T_Contacts
--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989
LEFT JOIN LATERAL
(
SELECT
--MAP_CTCOU_UID
MAP_CTCOU_CT_UID
,MAP_CTCOU_COU_UID
,MAP_CTCOU_DateFrom
,MAP_CTCOU_DateTo
FROM T_MAP_Contacts_Ref_OrganisationalUnit
WHERE MAP_CTCOU_SoftDeleteStatus = 1
AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID
/*
AND
(
(__in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo)
AND
(__in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom)
)
*/
ORDER BY MAP_CTCOU_DateFrom
LIMIT 1
) AS FirstOE
Try using a subquery in your ON clause. An abstract example:
SELECT
*
FROM table1
JOIN table2 ON table2.id = (
SELECT id FROM table2 WHERE table2.table1_id = table1.id LIMIT 1
)
WHERE
...