ORA-00936: missing expression distinct on oracle - sql

i am using oracle 10g plsql,
my query is:
select DISTINCT ON("Rental"."pkRentalId") "pkRentalId",
to_number("Reservation"."ReservationNo") "ReservationNo",
to_char("Rental"."RentalNo") "RentalNo",
to_char(segmentTable."Text"||'-'||rateTypeTable."Text") "RateType",
to_char("Debtor"."DebtorName") "DebtorName",
to_char("Rates"."RateName") "RateName",
to_char("Renter"."FirstName"||' '||"Renter"."LastName") "Renter",
to_date("Rates"."ValidFrom") "ValidFrom",
to_date("Rates"."ValidTo") "ValidTo",
round(to_number(to_number("ReservationDuration"."ExpectedCheckinDateTime"-"ReservationDuration"."DispatchDateTime") *to_number("Rates"."UnitRate")),2) "RentalAmount",
to_number("Deductions"."Amount") "Deduction",
to_number("Billing"."DiscountAmount") "Discount"
from "Reservation"
inner join "Rental" on "Rental"."pkRentalId"="Reservation"."fkRentalId"
inner join "Rates" on "Rates"."pkRateId"="Reservation"."fkRateId"
inner join "Renter" on "Renter"."fkReservationId"="Reservation"."pkReservationId"
inner join "Billing" on "Billing"."pkBillingId"="Reservation"."fkBillingId"
inner join "Deductions" on "Deductions"."fkRentalId"="Rental"."pkRentalId"
inner join "Debtor" on "Debtor"."pkDebtorId"="Rates"."fkDebtorId"
inner join "EnumerationValue" segmentTable on segmentTable."pkEnumerationValueId"="Reservation"."fkSegmentId"
inner join "EnumerationValue" rateTypeTable on rateTypeTable."pkEnumerationValueId"="Reservation"."fkRateTypeId"
inner join "ReservationDuration" on "ReservationDuration"."pkDurationLocationId"="Reservation"."fkDurationId"
where "Reservation"."IsDeleted"='N'
it is returning me :
ORA-00936: missing expression
00936. 00000 - "missing expression"
*Cause:
*Action:
Error at Line: 4 Column: 17
What is the correct format of distinct on in oracle pl/sql? I want to return all the distinct "pkRentalId" values and the maximum value for all the other columns.

If you want the maximum value for each of the other columns, you'd need to do a GROUP BY, not a DISTINCT with the max aggregate function on all the other columns.
select "Rental"."pkRentalId",
max(to_number("Reservation"."ReservationNo")) "ReservationNo",
max(to_char("Rental"."RentalNo")) "RentalNo",
max(to_char(segmentTable."Text"||'-'||rateTypeTable."Text")) "RateType",
max(to_char("Debtor"."DebtorName")) "DebtorName",
max(to_char("Rates"."RateName")) "RateName",
max(to_char("Renter"."FirstName"||' '||"Renter"."LastName")) "Renter",
max(to_date("Rates"."ValidFrom")) "ValidFrom",
max(to_date("Rates"."ValidTo")) "ValidTo",
max(round(to_number(to_number("ReservationDuration"."ExpectedCheckinDateTime"-"ReservationDuration"."DispatchDateTime") *to_number("Rates"."UnitRate")),2)) "RentalAmount",
max(to_number("Deductions"."Amount")) "Deduction",
max(to_number("Billing"."DiscountAmount")) "Discount"
from ...
where ...
group by "Rental"."pkRentalId"
Now, from a requirements standpoint, given the query you have, it seems unusual to want to get the maximum value for all the other columns. That's going to mix data from multiple rows together in a way that doesn't seem to make sense to me.

The distinct on operator from Postgres usually translates to using the window function row_number() where the "distinct" columns are used for the partition by part and the order by is used to select the row you want:
select *
from (
select
row_number() over partition by ("Rental"."pkRentalId" order by "Reservation"."ReservationNo") as rn,
... other columns
from "Reservation"
... joins
where "Reservation"."IsDeleted"='N'
)
where rn = 1
By changing the order by in the window definition you can pick which row you want ("first", "last", "third").
The difference to the solution using max() is that it will preserve the values that belong together in one row.

Related

Outer join for Alias name and column name -Oracle

I had a working sample query earlier in my code as mentioned below.
SELECT DISTINCT
nombre_aplicacion,
APLICACION,
NOMBRE_APLCODE,
DESCRIPCION,
AREAFUNC
FROM (
select **CODAPLICATION nombre_aplicacion**,
APLICACION,
NOMBRE_APLCODE,
DESCRPTION,
AREAFUNC
from admin.VW_APLICACIONES#dblink,
admin.VW_PRODUCTOS#dblink
where **nombre_aplicacion (+) = CODAPLICATION**
)
WHERE 1=1
ORDER BY nombre_aplicacion ASC;
When I try similar type of query with different tables I was getting error as invalid ORA-00904: "NOMBRE_APLICACION": invalid identifier.
If I remove nombre_aplicacion (+) = CODAPLICATION in where condition query is fetching the result. Can any one suggest why I was facing error as its working earlier with sample query and I was getting error? Is this join is valid?
The query is not valid as:
In the inner sub-query you select areafunc and in the outer query you use area which does not appear in the inner sub-query so will not be available.
In the inner sub-query, you define CODAPLICATION to have the alias nombre_aplicacion and then you try to use that alias in the WHERE clause as a join condition; that will not work.
You have not described which column belongs to which table but you want something like:
SELECT DISTINCT
a.codaplication AS nombre_aplicacion,
a.aplicacion,
a.nombre_aplcode,
p.descrption,
p.areafunc
from APLICACIONES a
LEFT OUTER JOIN PRODUCTOS p
ON (a.primary_key_column = p.foreign_key_column)
ORDER BY nombre_aplicacion ASC;
Note: you are going to have to correct the code to give the correct table aliases for each column and give the correct columns for the join condition.

Joining two tables, sorting and finding the Top revenue values

I am trying to create a query with the top 3 shops that have the highest average revenue amount and retail_type being fashion and shoes. I have to join 3 tables where I have to join 2 to the 1st one. Something seems to be wrong with the syntax below:
Select * from (Select
a.shop_id,
c.retail_type,
avg(b.revenue_amount) as avg_revenue_amount
From
shops a
Left join rev b on a.shop_id = b.shop_id
Left join trans c on b.trans_id = c.trans_id
Where
c.retail_type in (‘fashion’, ‘ shoes ’)
Group by
1,
2
Order by
avg_revenue_amount desc)
limit 10;
I would recommend writing the query as:
select s.shop_id, t.retail_type,
avg(r.revenue_amount) as avg_revenue_amount
from shops s join
rev r
on s.shop_id = r.shop_id join
trans
t
on r.trans_id = t.trans_id
where t.retail_type in ('fashion', 'shoes')
group by s.shop_id, t.retail_type
order by avg_revenue_amount desc
limit 10;
You don't specify your database, but the following are potentially problematic:
Bad quotes in the in clause.
Lack of alias after the derived table.
Use of numeric placeholders in GROUP BY.
Not all of these are necessarily errors, but they could be depending on your database.
The following would not cause a syntax error but might cause other problems:
Spaces around a string for an IN comparison means the comparison might not work.
Use of arbitrary letters for table aliases makes the query really hard to follow.
The WHERE clause turns the LEFT JOINs to inner joins so LEFT JOINs are highly misleading.
The subquery is superfluous.
You have extra bracket on the line:
avg_revenue_amount) desc)
Also you have typo on the second line: a.shop.id -> a.shop_id and another problem with quotes: ‘fashion’, ‘ shoes ’ -> 'fashion', 'shoes'
Check edited query on the SQL Fiddle.

RedShift SQL subquery with Inner join

I am using AWS Redshift SQL. I want to inner join a sub-query which has group by and inner join inside of it. When I do an outside join; I am getting an error that column does not exist.
Query:
SELECT si.package_weight
FROM "packageproduct" ub "clearpathpin" cp ON ub.cpipr_number = cp.pin_number
INNER JOIN "clearpathpin" cp ON ub.cpipr_number = cp.pin_number
INNER JOIN (
SELECT sf."AWB", SUM(up."weight") AS package_weight
FROM "productweight" up ON up."product_id" = sf."item_id"
GROUP BY sf."AWB"
HAVING sf."AWB" IS NOT NULL
) AS si ON si.item_id = ub.order_item_id
LIMIT 100;
Result:
ERROR: column si.item_id does not exist
It's simply because column si.item_id does not exist
Include item_id in the select statement for the table productweight
and it should work.
There are many things wrong with this query.
For your subquery, you have an ON statement, but it is not joining:
FROM "productweight" up ON up."product_id" = sf."item_id"
When you join the results of this subquery, you are referencing a field that does not exist within the subquery:
SELECT sf."AWB", SUM(up."weight") AS package_weight
...
) AS si ON si.item_id = ub.order_item_id
You should imagine the subquery as creating a new, separate, briefly-existing table. The outer query than joins that temporary table to the rest of the query. So anything not explicitly resulted in the subquery will not be available to the outer query.
I would recommend when developing you write and run the subquery on its own first. Only after it returns the results you expect (no errors, appropriate columns, etc) then you can copy/paste it in as a subquery and start developing the main query.

SQL subquery multiple times error

I am making a subquery but I am getting a strange error
The column 'RealEstateID' was specified multiple times for 'NotSold'.
here is my code
SELECT *
FROM
(SELECT *
FROM RealEstatesInfo AS REI
LEFT JOIN Purchases AS P
ON P.RealEstateID=REI.RealEstateID
WHERE DateBought IS NULL) AS NotSold
INNER JOIN OwnerEstate AS OE
ON OE.RealEstateID=NotSold.RealEstateID
It's on SQL server by the way.
That's because there will be 2 realestiteids in your subquery. You need to change it to explicitly list the columns from both table and only include 1 realestateid. It doesn't matter which as you use it for your join.
If you're very Lazy you can select rei.* and only name the p cols apart from realestateid.
Btw select * is probably never a good idea in sub queries or derived tables or ctes.

SQL Server query returns duplicate results because of multiple group by columns

Here is my query :
select
Booking.BookingID, Booking.BookingNo,
Booking.Vcode, Booking.TransID,
Booking.StatusID,Booking.BookingDate,
BookingContact.FirstName, BookingContact.MiddleName, BookingContact.LastName,
Schedule.DepatureDateTime as DepartDate,
Origin.City as Origin, Destination.City as Destination,
PaxJourney.TripTypeID
from
Booking
inner join
Pax on Booking.BookingID = Pax.BookingID
inner join
PaxJourney on Pax.PaxID = PaxJourney.PaxID
inner join
Schedule on PaxJourney.ScheduleID = Schedule.ScheduleID
inner join
City as Origin on Schedule.DepartureCityID = Origin.CityID
inner join
City as Destination on Schedule.ArrivalCityID = Destination.CityID
inner join
BookingContact on Booking.BookingID = BookingContact.BookingID
group by
Booking.BookingID ,Booking.BookingNo, Booking.Vcode, Booking.TransID,
Booking.StatusID,Booking.BookingDate, BookingContact.FirstName,
BookingContact.MiddleName, BookingContact.LastName,
Schedule.DepatureDateTime, Origin.City, Destination.City, PaxJourney.TripTypeID
Question: how to remove multiple group by fields in my query?
I got duplicate data because of these two "Origin.City, Destination.City" columns when I remove any one column in group by section I got error :
Msg 8120, Level 16, State 1, Line 22
Column 'City.City' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I want to use group by with one column like "group by Booking.BookingID"
Well you need to use a aggregation function, as the error stated. All columns you won't group, must use an aggregation.
If you have only a group by based on Booking.BookingId you need to use an aggregation function on all other columns you select. For example:
SELECT Booking.BookingId, MAX(City.City) as City
FROM Booking
GROUP BY Booking.BookingId
Even if all rows of City.City show the same value, SQL Server won't execute your query, as it may occur a duplicate value with different contents. This way you need to define the proper aggregation (e.g. MIN,MAX,AVG, etc.) on all not grouped columns.