Subquery within scalar subquery fails with error ORA-00936 Missing Expression - sql

This is the query that does not work:
SELECT distinct ord.DateOrdered
, (SELECT docno
FROM th_mm_c_orderline_history
WHERE th_mm_c_orderline_history_id
in (SELECT max(th_mm_c_orderline_history_id)
FROM th_mm_c_orderline_history
GROUP BY c_orderline_id )
order by docno,c_orderline_id) as docno
FROM c_order ord
INNER JOIN c_orderline on c_orderline.c_order_id = ord.c_order_id
INNER JOIN th_mm_c_orderline_history
on th_mm_c_orderline_history.c_order_id=ord.c_order_id
It is throwing me ORA-00936 Missing expression error
This query works fine:
SELECT docno
FROM th_mm_c_orderline_history
WHERE th_mm_c_orderline_history_id
in (SELECT max(th_mm_c_orderline_history_id)
FROM th_mm_c_orderline_history
GROUP BY c_orderline_id )
order by docno,c_orderline_id as docno

Just remove the order by clause from the inline select. You can not use orde by clause there. You can use it in the outer select if you need it...This is how you can do all three of them without the error:
SELECT distinct ord.DateOrdered
, (SELECT docno FROM th_mm_c_orderline_history
WHERE th_mm_c_orderline_history_id
in (SELECT max(th_mm_c_orderline_history_id)
FROM th_mm_c_orderline_history
GROUP BY c_orderline_id)
) as docno
FROM c_order ord
INNER JOIN c_orderline on c_orderline.c_order_id = ord.c_order_id
INNER JOIN th_mm_c_orderline_history on th_mm_c_orderline_history.c_order_id=ord.c_order_id

You can use "order by statement" end of the whole select statement. Because of not use the column C_ORDERLINE_ID in select statement, it can be error in order by statement. Try this version in below.
SELECT DISTINCT
C_ORDER.DATEORDER,
(SELECT DOCNO
FROM TH_MM_C_ORDERLINE_HISTORY
WHERE C_ORDER_ID = C_ORDER_ID
AND TH_MM_C_ORDERLINE_HISTORY_ID IN ( SELECT MAX (TH_MM_C_ORDERLINE_HISTORY_ID)
FROM TH_MM_C_ORDERLINE_HISTORY
GROUP BY C_ORDERLINE_ID)) AS DOCNO,
C_ORDER.DOCUMENTNO
FROM C_ORDER
INNER JOIN C_ORDERLINE ON C_ORDERLINE.C_ORDER_ID = C_ORDER_ID
ORDER BY DOCNO, C_ORDERLINE_ID;

Related

Inner join same table syntax error

I'm trying to run an inner join between this same table. What is wrong with my syntax?
(SELECT user_key, bill_number, MAX(payment_date) AS payment_date
FROM billpayment) bpt
INNER JOIN (SELECT * FROM billpayment) bp
ON bp.user_key=bpt.user_key
AND bp.bill_number=bpt.bill_number
AND bp.payment_date=bpt.payment_date
GROUP BY user_key, bill_number;
It says that the sql command is not properly ended at the parenthesis in 'billpayment)'
SELECT
user_key,
bill_number,
MAX(payment_date) AS payment_date
FROM billpayment bpt
INNER JOIN billpayment bp
ON bp.user_key=bpt.user_key
AND bp.bill_number=bpt.bill_number AND bp.payment_date=bpt.payment_date
GROUP BY
user_key, bill_number
;
On Oracle Try this:
SELECT *
FROM (SELECT user_key, bill_number, MAX (payment_date) AS payment_date FROM billpayment) bpt
INNER JOIN billpayment bp
ON bp.user_key = bpt.user_key AND bp.bill_number = bpt.bill_number AND bp.payment_date = bpt.payment_date
GROUP BY user_key, bill_number;
Can't test it without the table structure.
How about just using analytic functions?
select bp.*,
max(bp.paymentdate) over (partition by user_key, bill_number) as max_payment_date
from billpayment
If you want the fields on the max payment date:
select bp.*
from (select bp.*,
max(bp.paymentdate) over (partition by user_key, bill_number) as max_paymentdate
from billpayment
) bp
where paymentdate = max_paymentdate;
On mySQL, you can try something like:
SELECT bpt.user_key, bpt.bill_number, MAX(bpt.payment_date) AS payment_date
FROM billpayment bpt
INNER JOIN (SELECT * FROM billpayment) bp
ON bp.user_key=bpt.user_key
AND bp.bill_number=bpt.bill_number
AND bp.payment_date=bpt.payment_date
GROUP BY bpt.user_key, bpt.bill_number;

Getting count over() value after distinct executed

I have a query such as
select
distinct
t.*,
t.name + ' ' + t.lastname as customername
count(t.id) over() as count
from
table t
inner join othertable o
on t.id = o.tableid
where t.blah = 'aaa'
The problem is that the count over() calculates the results before the distinct is executed and therefore returns an incorrect value.
I could remove the distinct and use group by but this will give the count for each group and I want the sum of those values.
I could do a subquery but the problem is this query is getting built up inside an application so I'd have to do some string manipulation to add the where clause to the subquery and main sql body.
Is there a way to get the count show the results after the distinct is executed?
Thanks
This should solve the problem
select count(v.col_a) over() as count,
v.*
from (select distinct t.col_a, t.col_b, ... --all columns you need
t.name + ' ' + t.lastname as customername
from table t
inner join othertable o on t.id = o.tableid
where t.blah = 'aaa') v
Use group by, but use the correct expression:
select t.*,
t.name + ' ' + t.lastname as customername
sum(count(t.id)) over() as total_count
from table t inner join
othertable o
on t.id = o.tableid
where t.blah = 'aaa'
group by . . .

Join two tables returning only one row from the second table

I have this query:
SELECT t_ticket.ticketID, t_ticket.addedDate, t_ticket.question,
t_ticket.code, t_ticket.priority, t_actionTicket.addedDateAction, t_actionTicket.title
FROM t_actionTicket INNER JOIN
t_ticket ON t_actionTicket.ticketID_FK = t_ticket.ticketID INNER JOIN
(SELECT ticketID_FK, MAX(addedDateAction) AS maxDate
FROM t_actionTicket AS t_actionTicket_1
WHERE (t_actionTicket.userID_FK <> #userid)
GROUP BY ticketID_FK) AS b ON t_actionTicket.ticketID_FK = b.ticketID_FK AND t_actionTicket.addedDateAction = b.maxDate
WHERE (t_ticket.supporterID_FK IN
(SELECT supporterID
FROM t_Supporter
WHERE (userID_FK = #userid)))
I want to return just the latest record in t_actionTicket table for each row in t_ticket table that t_actionTicket.userID_FK <> #userid.
but I have this error:
The multi-part identifier "t_actionTicket.userID_FK" could not be
bound.
Problem in your query is
FROM t_actionTicket AS t_actionTicket_1
WHERE t_actionTicket.userID_FK <> #userid -- here
You cannot use t_actionTicket alias name inside inner join select query. You need to use t_actionTicket_1. It is possible only in sub-query
Try this better way of doing it
;WITH cte
AS (SELECT t_ticket.ticketID,
t_ticket.addedDate,
t_ticket.question,
t_ticket.code,
t_ticket.priority,
t_actionTicket.addedDateAction,
t_actionTicket.title,
Row_number()
OVER(
partition BY ticketID_FK
ORDER BY addedDateAction DESC) RN
FROM t_actionTicket
INNER JOIN t_ticket
ON t_actionTicket.ticketID_FK = t_ticket.ticketID
WHERE t_ticket.supporterID_FK IN (SELECT supporterID
FROM t_Supporter
WHERE userID_FK = #userid))
SELECT *
FROM cte
WHERE rn = 1
You can write this logic using row_number() instead of additional nested queries:
SELECT t.ticketID, t.addedDate, t.question, t.code, t.priority,
ta.addedDateAction, ta.title AS Expr1
FROM t_Ticket t INNER JOIN
(SELECT ta.*,
ROW_NUMBER() OVER (PARTITION BY ta.ticketID_FK ORDER BY ta.addedDateAction DESC) as seqnum
FROM t_actionTicket ta
) ta
ON t.ticketId = ta.ticketId_FK and ta.seqnum = 1
WHERE t.supporterID_FK IN (SELECT supporterID
FROM t_Supporter
WHERE userID_FK = #userid
);
Note that table aliases make the query easier to write and to read.
Try this query
SELECT t_ticket.ticketID, t_ticket.addedDate, t_ticket.question,
t_ticket.code, t_ticket.priority, t_actionTicket.addedDateAction, t_actionTicket.title
FROM t_actionTicket
INNER JOIN t_ticket ON t_actionTicket.ticketID_FK = t_ticket.ticketID
INNER JOIN (SELECT ticketID_FK, MAX(addedDateAction) AS maxDate
FROM t_actionTicket AS t_actionTicket_1
WHERE (t_actionTicket_1.userID_FK <> #userid)
GROUP BY ticketID_FK) AS b ON t_actionTicket.ticketID_FK = b.ticketID_FK AND t_actionTicket.addedDateAction = b.maxDate
WHERE (t_ticket.supporterID_FK IN
(SELECT supporterID
FROM t_Supporter
WHERE (userID_FK = #userid)))

ORA-00907: missing right parenthesis at the bottom of code - why? Syntax is good

select racuni.str_id
from racuni
where racuni.str_id in
(select racuni.str_id
from racuni
join stavke
on (racuni.racuni_id = stavke.rcn_id)
group by racuni.str_id
order by sum(stavke.iznos_kamate) desc
)
and rownum = 1;
You must first do an order by in the innermost query, then select the first row in the inner query, and then get that racun in the outer query. Like this:
select racuni.*
from racuni
where racuni.str_id in
(select str_id
from
(select racuni.str_id
from racuni
join stavke
on (racuni.racuni_id = stavke.rcn_id)
group by racuni.str_id
order by sum(stavke.iznos_kamate) desc )
where rownum = 1 );

SQL Error of Undefined Column

SELECT
Stockmain.VRNOA,
item.description as item_description,
party.name as party_name,
stockmain.vrdate,
stockdetail.qty,
stockdetail.rate,
stockdetail.amount,
ROW_NUMBER() OVER (ORDER BY VRDATE) AS RowNum
FROM StockMain
INNER JOIN StockDetail
ON StockMain.stid = StockDetail.stid
INNER JOIN party
ON party.party_id = stockmain.party_id
INNER JOIN item
ON item.item_id = stockdetail.item_id
WHERE stockmain.etype='purchase' AND RowNum BETWEEN 1 and (1 + 100)
ORDER BY VRDATE DESC
I am trying to execute this query on SQL Server and it keeps giving this error
Invalid column name 'RowNum'.
Can anyone please have a look and tell me what I'm doing wrong here?
Update
The query I was originally using was
SELECT
*
FROM (
SELECT
Stockmain.VRNOA,
item.description as item_description,
party.name as party_name,
stockmain.vrdate,
stockdetail.qty,
stockdetail.rate,
stockdetail.amount,
ROW_NUMBER() OVER (ORDER BY VRDATE DESC) AS RowNum --< ORDER BY
FROM StockMain
INNER JOIN StockDetail
ON StockMain.stid = StockDetail.stid
INNER JOIN party
ON party.party_id = stockmain.party_id
INNER JOIN item
ON item.item_id = stockdetail.item_id
WHERE stockmain.etype='purchase'
) AS MyDerivedTable
WHERE
MyDerivedTable.RowNum BETWEEN 1 and 5
but the data in the data is immense and using this query slows down the retrieval process, so I modified the query as above and now I'm getting this error of undefined column.
It looks like you're trying to perform a paging operation, or at least a query that is greatly simplified using the new paging operators in SQL Server 2012, OFFSET and FETCH:
SELECT
Stockmain.VRNOA,
item.description as item_description,
party.name as party_name,
stockmain.vrdate,
stockdetail.qty,
stockdetail.rate,
stockdetail.amount
FROM StockMain
INNER JOIN StockDetail
ON StockMain.stid = StockDetail.stid
INNER JOIN party
ON party.party_id = stockmain.party_id
INNER JOIN item
ON item.item_id = stockdetail.item_id
WHERE stockmain.etype='purchase'
ORDER BY VRDATE DESC
OFFSET 0 ROWS
FETCH NEXT 100 ROWS ONLY
For more information, please see the following: http://www.dbadiaries.com/new-t-sql-features-in-sql-server-2012-offset-and-fetch
Put it in a subquery, the ROW_NUMBER() can't be used in the WHERE clause, not to mention you can't use aliases created in the SELECT list in the WHERE clause:
SELECT *
FROM (SELECT
Stockmain.VRNOA,
item.description as item_description,
party.name as party_name,
stockmain.vrdate,
stockdetail.qty,
stockdetail.rate,
stockdetail.amount,
ROW_NUMBER() OVER (ORDER BY VRDATE) AS RowNum
FROM StockMain
INNER JOIN StockDetail
ON StockMain.stid = StockDetail.stid
INNER JOIN party
ON party.party_id = stockmain.party_id
INNER JOIN item
ON item.item_id = stockdetail.item_id
WHERE etype='purchase'
)sub
WHERE RowNum BETWEEN 1 and (1 + 100)
ORDER BY VRDATE DESC
Update: After seeing your update it's clear you've got a working query but are trying to optimize it, even if you could move the ROW_NUMBER() inside the main query it wouldn't improve performance, it still has to perform the intensive ORDER on the full data set. Indexing VRDATE will help.
This is a situation where you need to use a memory table or a temp table;
to use a memory table;
DECLARE #Table TABLE(ROWID int identity,<all your columns>)
INSERT INTO #Table (<your columns>)
SELECT
Stockmain.VRNOA,
item.description as item_description,
party.name as party_name,
stockmain.vrdate,
stockdetail.qty,
stockdetail.rate,
stockdetail.amount,
ROW_NUMBER() OVER (ORDER BY VRDATE) AS RowNum
FROM StockMain
INNER JOIN StockDetail
ON StockMain.stid = StockDetail.stid
INNER JOIN party
ON party.party_id = stockmain.party_id
INNER JOIN item
ON item.item_id = stockdetail.item_id
WHERE etype='purchase'
SELECT <columns you need> FROM #Table
If you use a #temp table, make sure to drop it after the SELECT statement.