How to change CTE coding to INLINE view? Oracle SQL - sql

My system doesn't allow CTE in coding and the first word has to always be SELECT.
Could someone explain (ideally in a Oracle SQL for dummies format) how I would go about changing code written with CTE into INLINE code?
As an example of CTE code:
WITH table1
AS (SELECT enquiry_status_log.enquiry_number,
enquiry_status_log.enquiry_log_number,
follow_up.follow_up_name,
enquiry_status_log.follow_up_date,
RANK ()
OVER (PARTITION BY enquiry_status_log.enquiry_number
ORDER BY enquiry_status_log.enquiry_log_number DESC)
rn
FROM enquiry_status_log
JOIN follow_up
ON enquiry_status_log.follow_up_code =
follow_up.follow_up_code)
SELECT enquiry_number,
enquiry_log_number,
follow_up_name,
follow_up_date
FROM table1
WHERE rn = 1
ORDER BY enquiry_number, enquiry_log_number
How would I write this (please, VERY easy to understand) so that SELECT would be the first word in the code and CTE wasn't used?

Your CTE is used only once in your query, so you can simply turn it to a subquery:
SELECT enquiry_number,
enquiry_log_number,
follow_up_name,
follow_up_date
FROM (
SELECT
e.enquiry_number,
e.enquiry_log_number,
f.follow_up_name,
e.follow_up_date,
RANK () OVER (
PARTITION BY e.enquiry_number
ORDER BY e.enquiry_log_number DESC
) rn
FROM enquiry_status_log e
JOIN follow_up f ON e.follow_up_code = f.follow_up_code
) table1
WHERE rn = 1
ORDER BY enquiry_number, enquiry_log_number
Note: table aliases make the query shorter and easier to read. I modified you query to use them.
Also, it is possible that your query could be rewritten to use a correlated subquery for filtering instead of rank(). In Oracle, this could lead to better performance:
SELECT
e.enquiry_number,
e.enquiry_log_number,
f.follow_up_name,
e.follow_up_date
FROM enquiry_status_log e
JOIN follow_up f ON e.follow_up_code = f.follow_up_code
WHERE e.enquiry_log_number = (
SELECT MAX(enquiry_log_number)
FROM enquiry_status_log e1
WHERE e.enquiry_number = e1.enquiry_number
)
ORDER BY e.enquiry_number, e.enquiry_log_number

Related

multiple joins to same sub query

I need to join to the same table repeatedly but this looks ugly. Any suggestions appreciated. Below is simplified SQL, I have 8 tables in the subquery and it produces many duplicate records of the same date, so I need to find only the newest record for each client. (I don't think DB and/or version should matter, but I am using DB2 11.1 LUW)
select c.client_num, a.eff_date, t.trx_date
from client c
join address a on(a.id = c.addr_id)
join transaction t on(t.addr_id = a.id)
{many other joins}
where {many conditions};
select SQ.*
from [ABOVE_SUBQUERY] SQ
join
(select client_num, max(eff_date) AS newest_date from [ABOVE_SUBQUERY] group by client_num) AA
ON(SQ.client_num = AA.client_num and SQ.eff_date = AA.newest_date)
join
(select client_num, max(trx_date) AS newest_date from [ABOVE_SUBQUERY] group by client_num) TT
ON(SQ.client_num = TT.client_num and SQ.trx_date = TT.newest_date)
I need to fine only the newest record for each client.
Can't you just use row_number()?
select t.*
from (select t.*,
row_number() over (partition by client_num order by eff_date desc, eff_time desc) as seqnum
from <whatever> t
) t
where seqnum = 1;

Joining Onto Partition Statement HANA SQL

I am trying to join two tables to the following query:
SELECT "NUMBER",
"U_ANALYZED_DATE",
"DV_SALES_ACCOUNT",
"U_USD_TOTAL_POTENTIAL_NNACV"
FROM
(select *, row_number() over ( partition by "DV_SALES_ACCOUNT" order by "U_ANALYZED_DATE" desc ) rownum
from "SURF_RT"."SALES_REQUEST")
WHERE rownum = 1
AND "DV_SALES_CATEGORY" = 'Compliance'
AND "DV_STATE" NOT IN ('Closed Canceled')
AND (YEAR("U_ANALYZED_DATE") = '2019' AND MONTH("U_ANALYZED_DATE") IN ('10','11','12')
OR YEAR("U_ANALYZED_DATE") = '2020' AND MONTH("U_ANALYZED_DATE") IN ('1','2','3'))
AND "U_USD_TOTAL_POTENTIAL_NNACV" > 0
ORDER BY "U_ANALYZED_DATE" desc
The tables should be joined as follows:
JOIN "SURF_RT"."SALES_ACCOUNT" on "SURF_RT"."SALES_ACCOUNT"."NAME" = "SURF_RT"."SALES_REQUEST"."DV_SALES_ACCOUNT"
JOIN "SURF_RT"."SALES_CONTRACT" on "SURF_RT"."SALES_CONTRACT"."DV_ACCOUNT" = "SURF_RT"."SALES_REQUEST"."DV_SALES_ACCOUNT"
I am getting an error no matter what I try and it has to be because of the partition. Does anyone know the solution here?
I suspect that you just need to alias the derived table so you can then refer to join it. In many databases this is mandatory anyway, but apparently not in Hana (otherwise your original query would not run).
But to join on a derived table (the resultset that is generated by the subquery), alias do help:
SELECT
...
FROM
(
select
*,
row_number() over ( partition by "DV_SALES_ACCOUNT" order by "U_ANALYZED_DATE" desc ) rownum
from "SURF_RT"."SALES_REQUEST"
) sr -- table alias
JOIN "SURF_RT"."SALES_ACCOUNT"
ON "SURF_RT"."SALES_ACCOUNT"."NAME" = "SURF_RT"."SALES_REQUEST"."DV_SALES_ACCOUNT"
JOIN "SURF_RT"."SALES_CONTRACT"
ON "SURF_RT"."SALES_CONTRACT"."DV_ACCOUNT" = sr."DV_SALES_ACCOUNT" --reference to the derived table
WHERE
...
Side notes:
you should use table aliases for other tables involved in the query too, in order to make the code more readable
you should also prefix each column in the query with the identifier of the table it belongs to, so the query is unambiguous (and easier to maintain)
The problem with this query is not "that the where rownum = 1 needs to be at the end" but that the OP got confused by the bracketing of SQL expression.
More specifically, trying to reference the sub-query data by specifying join conditions against the base table that is used in the sub-query:
JOIN "SURF_RT"."SALES_ACCOUNT"
on "SURF_RT"."SALES_ACCOUNT"."NAME" = "SURF_RT"."SALES_REQUEST"."DV_SALES_ACCOUNT"
JOIN "SURF_RT"."SALES_CONTRACT"
on "SURF_RT"."SALES_CONTRACT"."DV_ACCOUNT" = "SURF_RT"."SALES_REQUEST"."DV_SALES_ACCOUNT"
Since the sub-query (derived table) is used in the query and should be used for the join, it needs to be referred in the join condition, instead.
So, yes, it needs a table alias here and the join conditions need to refer to it.
SELECT
...
FROM
(select *
, row_number() over
(partition by "DV_SALES_ACCOUNT"
order by "U_ANALYZED_DATE" desc) rownum
from
"SURF_RT"."SALES_REQUEST") sr
INNER JOIN "SURF_RT"."SALES_ACCOUNT" sa
on sa."NAME" = sr."DV_SALES_ACCOUNT"
INNER JOIN "SURF_RT"."SALES_CONTRACT" sc
on sc."DV_ACCOUNT" = sr."DV_SALES_ACCOUNT"
WHERE
sr.rownum = 1
AND "DV_SALES_CATEGORY" = 'Compliance'
AND "DV_STATE" NOT IN ('Closed Canceled')
AND (YEAR("U_ANALYZED_DATE") = '2019'
AND MONTH("U_ANALYZED_DATE") IN ('10','11','12')
OR YEAR("U_ANALYZED_DATE") = '2020'
AND MONTH("U_ANALYZED_DATE") IN ('1','2','3'))
AND "U_USD_TOTAL_POTENTIAL_NNACV" > 0
ORDER BY
"U_ANALYZED_DATE" desc;
With just this little bit of standard SQL syntax and formatting of code the query got a lot easier to understand.
Now it's even obvious that the IN conditions for MONTH and YEAR should in fact be integers, not strings as these functions return integers.
SELECT
...
FROM
(SELECT *
, row_number() over
(partition by "DV_SALES_ACCOUNT"
order by "U_ANALYZED_DATE" desc) rownum
FROM
"SURF_RT"."SALES_REQUEST") sr
INNER JOIN "SURF_RT"."SALES_ACCOUNT" sa
on sa."NAME" = sr."DV_SALES_ACCOUNT"
INNER JOIN "SURF_RT"."SALES_CONTRACT" sc
on sc."DV_ACCOUNT" = sr."DV_SALES_ACCOUNT"
WHERE
sr.rownum = 1
AND "DV_SALES_CATEGORY" = 'Compliance'
AND "DV_STATE" NOT IN ('Closed Canceled')
AND ( YEAR("U_ANALYZED_DATE") = 2019
AND MONTH("U_ANALYZED_DATE") IN (10, 11, 12)
OR YEAR("U_ANALYZED_DATE") = '2020'
AND MONTH("U_ANALYZED_DATE") IN (1 , 2 , 3 )
)
AND "U_USD_TOTAL_POTENTIAL_NNACV" > 0
ORDER BY
"U_ANALYZED_DATE" DESC

SQL SERVER make a row data to column

I'm currently making a program to store data in database sql server.
and the data is a cost that divided into max 5 column cost details.
As for the first row it labeled with 1 and second with 2, up to 5 row with same id.
So i'm making the table like the picture below. And Now i want to select the table from row to column like in the picture.
i'm making the query like this. I get the result like i want, but the problem is that the query cost like 5/more times the execution plan by just selecting the same table.
My question is, is there a way to make the result like in the picture just by selecting once the table or is there any other way to make like the result with better performance, i hear of using pivot for transposing row to column, but in my case i don't know how to do it. Thanks for reply
this is the execution plan https://www.brentozar.com/pastetheplan/?id=SJGJdaCB7
AND this is the query i used
select * FROM TblKecelakaanBiaya;
with tbl AS (
select *, ROW_NUMBER() OVER(PARTITION by id_kasus ORDER BY id_kasus) rn FROM TblKecelakaanBiaya
)
SELECT A.id_kasus, A.ket_biaya1, A.jlh_biaya1, C.ket_biaya2, C.jlh_biaya2,
D.ket_biaya3, D.jlh_biaya3, E.ket_biaya4, E.jlh_biaya4, F.ket_biaya5, F.jlh_biaya5
FROM (SELECT id_kasus, ket_biaya ket_biaya1, jlh_biaya jlh_biaya1 FROM tbl WHERE rn = 1) A
LEFT JOIN (SELECT id_kasus, ket_biaya ket_biaya2, jlh_biaya jlh_biaya2 FROM tbl WHERE rn = 2) C ON A.id_kasus = C.id_kasus
LEFT JOIN (SELECT id_kasus, ket_biaya ket_biaya3, jlh_biaya jlh_biaya3 FROM tbl WHERE rn = 3) D ON A.id_kasus = D.id_kasus
LEFT JOIN (SELECT id_kasus, ket_biaya ket_biaya4, jlh_biaya jlh_biaya4 FROM tbl WHERE rn = 4) E ON A.id_kasus = E.id_kasus
LEFT JOIN (SELECT id_kasus, ket_biaya ket_biaya5, jlh_biaya jlh_biaya5 FROM tbl WHERE rn = 5) F ON A.id_kasus = F.id_kasus
The execution plan for query 1 is just 1% and the other one is 99%.
Perhaps a Pivot inconcert with a Cross Apply.
Example
Select *
From (
Select id_kasus,item,value
From (Select * ,RN = Row_Number() over (Partition By id_kasus Order By id_kasus) From TblKecekakaanBiaya ) A
Cross Apply (values (concat('jih_biaya',RN),convert(varchar(150),jih_biaya))
,(concat('ket_biaya',RN),ket_biaya)
) b(item,value)
) src
Pivot (max(value) for item in ([ket_biaya1],[jih_biaya1],[ket_biaya2],[jih_biaya2],[ket_biaya3],[jih_biaya3],[ket_biaya4],[jih_biaya4],[ket_biaya5],[jih_biaya5]) ) pvt
Returns

How can I limit my select statement to return only one row based on creation date?

How to limit my select statement to only show one ?
If you are using Oracle 12c, you can use CROSS APPLY instead of INNER JOIN.
CROSS APPLY (SELECT inactivationremark,
createts
FROM t_se_internalrating ir
WHERE ir.RATINGSTATUS = 'Deactivated'
AND ir.PARTNERID = p1.ID
ORDER BY ir.createts DESC
fetch first 1 rows only
) ir
Look for CROSS APPLY or OUTER APPLY - this is the pattern you are looking for. See here.
If you are using a lower version, you can use the ROW_NUMBER function:
inner join
( SELECT
inactivationremark,
createts,
row_number() OVER(
PARTITION BY ir.partnerid ORDER BY ir.createts DESC) rn
FROM t_se_internalrating ir
WHERE ir.ratingstatus = 'Deactivated')
) ir
ON ir.partnerid = p1.id AND ir.rn < 2
The AND rn < 2 condition ensures that only the latest ratings are included.

access - row_number function?

I had this query, which gives me the desired results on postgres
SELECT
t.*,
ROW_NUMBER() OVER (PARTITION BY t."Internal_reference", t."Movement_date" ORDER BY t."Movement_date") AS "cnt"
FROM (SELECT
"Internal_reference",
MAX("Movement_date") AS maxtime
FROM dw."LO-D4_Movements"
GROUP BY "Internal_reference") r
INNER JOIN dw."LO-D4_Movements" t
ON t."Movement_date" = r.maxtime
AND t."Internal_reference" = r."Internal_reference"
Issue is I have to translate the query above on Access where the analytical function does not exist ...
I used this answer to build the query below
SELECT
t."Internal_reference",
t.from_code,
t.to_code,
t."Movement_date",
t.shipment_number,
t."PO_number",
t."Quantity",
t."Movement_value",
t."Site",
t."Import_date",
COUNT(*) AS "cnt"
FROM (
SELECT "Internal_reference",
MAX("Movement_date") AS maxtime
FROM dw."LO-D4_Movements"
GROUP BY "Internal_reference") r
LEFT OUTER JOIN dw."LO-D4_Movements" t
ON t."Movement_date" = r.maxtime AND t."Internal_reference" = r."Internal_reference"
GROUP BY
t.from_code,
t.to_code,
t."Movement_date",
t.shipment_number,
t."PO_number",
t."Quantity",
t."Movement_value",
t."Site",
t."Import_date",
t."Internal_reference"
ORDER BY t.from_code
Issue is I only have 1 in the cnt column.
I tried to tweak it by removing the internal_reference (see below)
SELECT
t.from_code,
t.to_code,
t."Movement_date",
t.shipment_number,
t."PO_number",
t."Quantity",
t."Movement_value",
t."Site",
t."Import_date",
COUNT(*) AS "cnt"
FROM (
SELECT "Internal_reference",
MAX("Movement_date") AS maxtime
FROM dw."LO-D4_Movements"
GROUP BY "Internal_reference") r
LEFT OUTER JOIN dw."LO-D4_Movements" t
ON t."Movement_date" = r.maxtime AND t."Internal_reference" = r."Internal_reference"
GROUP BY
t.from_code,
t.to_code,
t."Movement_date",
t.shipment_number,
t."PO_number",
t."Quantity",
t."Movement_value",
t."Site",
t."Import_date"
ORDER BY t.from_code
However, the results are even worse. The cnt is growing but it gives me the wrong cnt
Any help are more than welcome as I'm slow losing my sanity.
Thanks
Edit: Please find the sqlfiddle
I think Gordon-Linoff's code is close to what you want, but there are some typos I couldn't correct without a rewrite, so here's my attempt
SELECT
t1.Internal_reference,
t1.Movement_date,
t1.PO_Number as Combination_Of_Columns_Which_Make_This_Unique,
t1.Other_columns,
Count(1) AS Cnt
FROM
([LO-D4_Movements] AS t1
INNER JOIN [LO-D4_Movements] AS t2 ON
t1.Internal_reference = t2.Internal_reference AND
t1.Movement_date = t2.Movement_date)
INNER JOIN (
SELECT
t3.Internal_reference,
MAX(t3.Movement_date) AS Maxtime
FROM
[LO-D4_Movements] AS t3
GROUP BY
t3.Internal_reference
) AS r ON
t1.Internal_reference = r.Internal_reference AND
t1.Movement_date = r.Maxtime
WHERE
t1.PO_Number>=t2.PO_Number
GROUP BY
t1.Internal_reference,
t1.Movement_date,t1.PO_Number,
t1.Other_columns
ORDER BY
t1.Internal_reference,
t1.Movement_date,
Count(1);
In addition to within the max(movement_date) subquery, the main table is brought in twice. One version is the one for showing in your results, the other is for counting records to generate the sequence numbers.
Gordon said you need a unique id column for each row. And that's true if by "column" you mean to include derived columns also. Also it only needs to be unique within any combination of "internal_reference" and "Movement_date".
I've assumed, perhaps wrongly, that PO_Number will suffice. If not, concatenate with that (and some delimeters) other fields which will make it unique. The where clause will need updating to compare t1 and t2 for the "Combination of Columns which make this unique".
If, there is no appropriate combination available, I'm not sure it can be done without VBA and/or temp tables as The-Gambill suggested.
This is a real pain in MS Access, as far as I know. One method is a correlated subquery, but you need a unique id column on each row:
SELECT t.*,
(SELECT COUNT(*)
FROM (SELECT "Internal_reference", MAX("Movement_date") AS maxtime
FROM dw."LO-D4_Movements"
GROUP BY "Internal_reference"
) as t2
WHERE t2."Internal_reference" AND t."Internal_reference" AND
t2."Movement_date" = t."Movement_date" AND
t2.?? <= t.??
) as cnt
FROM (SELECT "Internal_reference", MAX("Movement_date") AS maxtime
FROM dw."LO-D4_Movements"
GROUP BY "Internal_reference"
) r INNER JOIN
dw."LO-D4_Movements" t
ON t."Movement_date" = r.maxtime AND
t."Internal_reference" = r."Internal_reference";
The ?? is for the id or creation date or something to allow the counting of rows.