Error thrown when converting SQL Server to Oracle SQL - oracle

I'm having to convert a lot of T-SQL statements this week to Oracle, most I have worked out but I'm still getting stuck on a few. The code below is one of them, I get the error that that the from clause is incorrect, I have tracked it down to this line of code:
NewBlc = Sls.CurrentBlc - SUM(NVL(Sls.NewBlc, 0) AS "New Balance",
I do not know what the correct format is to fix it. Any help appreciated.
SELECT
Sls.CustNme AS "Customer Name",
Sls.CustAddr AS "Customer Address",
Sls.CurrentBlc AS "Old Balance",
NewBlc = Sls.CurrentBlc - SUM(NVL(Sls.NewBlc, 0) AS "New Balance",
Tis
FROM
Customers,
(SELECT
c.Name AS CustNme,
c.Address AS CustAddr,
c.Balance AS CurrentBlc,
Cis(s.Item, c.Name) AS NewBlc,
Sis(c.name) AS Tis
FROM
CUST c
INNER JOIN
Sales o ON c.Name = o.cust
INNER JOIN
Purchases i on i.OrderNo = o.OrderNo
INNER JOIN
Contracters s on i.Item = s.Item
WHERE
o.Order_Date BETWEEN TO_DATE('01-01-2008', 'dd/mm/yyyy' )
AND TO_DATE('30-12-2009', 'dd/mm/yyyy')
GROUP BY
c.Name, c.Address, s.Item, c.Balance) Sls
GROUP BY
Sls.CustNme, Sls.CustAddr,Sls.CurrentBlc, NewBlc, Tis;

Related

How Can I Retrieve CLOBs for Unique Records in Group By

I have a table with one CLOB field (s.File) and I need to create a join on this table to get related data. However, in Oracle, CLOBs are not allowed in group by queries. What is the alternative? I have the following query for which I need to retrieve and serialize the CLOB, but I need the related information as well. See below:
select s.FileName, s.File, c.Name as CompanyName
from Source s inner join Company c on s.id = c.id
group by s.FileName, s.File, c.Name
I tried rewriting the query using row_number and partition by, but couldn't get that solution to work either. Any ideas would be greatly appreciated. The expected results would look something like
List item
:
FileName File CompanyName
interestincome.xlsx CLOB Woodson Company, Inc.
projectdetails.pdf CLOB Johnson Products, LLC
expenses2021.xlsx CLOB Marshall Consultants, LLP
If you want to get the unique CompanyName/Filename combinations and get a single FILE (rather than including the files in the GROUP BY clause) then:
SELECT filename,
(SELECT "FILE" FROM Source f WHERE f.ROWID = min_rowid) AS "FILE",
companyname
FROM (
select s.FileName,
c.Name as CompanyName,
MIN(s.ROWID) AS min_rowid
from Source s
inner join Company c
on s.id = c.id
group by
s.FileName, c.Name
)
If you want to check that the files are identical then you can use:
SELECT filename,
(SELECT "FILE" FROM Source f WHERE f.ROWID = min_rowid) AS "FILE",
companyname
FROM (
select s.FileName,
c.Name as CompanyName,
MIN(s.ROWID) AS min_rowid
from Source s
inner join Company c
on s.id = c.id
group by
s.FileName,
c.Name,
DBMS_CRYPTO.HASH(s."FILE", DBMS_CRYPTO.HASHSH256)
)
If you want to also consider the unlikely event of hash collisions then you can also compare the start of the files (since any hash collisions are likely to be between files that are not alike):
SELECT filename,
(SELECT "FILE" FROM Source f WHERE f.ROWID = min_rowid) AS "FILE",
companyname
FROM (
select s.FileName,
c.Name as CompanyName,
MIN(s.ROWID) AS min_rowid
from Source s
inner join Company c
on s.id = c.id
group by
s.FileName,
c.Name,
DBMS_LOB.SUBSTR(s."FILE", 1, 4000),
DBMS_CRYPTO.HASH(s."FILE", DBMS_CRYPTO.HASHSH256)
)

Missing Keyword Error in Oracle - Wrong Syntax WHERE Expression

I'm new to Oracle SQL, I'm being asked to do some scenarios to learn the different expressions and so on.
I'm currently working on this statement but I keep having trouble with syntax and trying to get my expressions in the correct place.
If you don't mind taking a look at what I'm doing wrong and helping me learn the correct syntax I'd appreciate it a lot.
I have to find everything in the Sale, SaleDetail, OrderStatus, Warehouse, User and StockDetail tables.
The fields I need to find are saleno, serialstart, serialend, the product description (label field), sale status (saleid (I think)), WarehouseName (WH.NAME)
Here below is the code I've written so far.
SELECT
S.SALENO,
SD.SERIALSTART,
SD.SERIALEND,
SDT.LABEL,
USR.USERNAME,
WH.NAME
FROM
ITR_SALE,
ITR_SALEDETAIL,
ITR_ORDER,
ITR_WAREHOUSE,
ITR_USER,
ITR_STOCKDETAIL
JOIN ITR_SALE S
JOIN ITR_SALEDETAIL SD ON S.ID = SD.SALENO
JOIN ITR_WAREHOUSE WH ON SD.ID = WH.NAME
JOIN ITR_ORDER ODR ON WH.ID = ODR.STATUSID
JOIN ITR_USER USR ON ODR.ID = USR.USERNAME
JOIN ITR_STOCKDETAIL ON USR.ID = SDT.LABEL
WHERE S.LASTSTATUSCHANGETIME
BETWEEN ('2016-01-01 00:00:00' AND '2016-12-31 23:59:59')
AND STATUSID = ('COMPLETED');
Below follows the error message
ORA-00905: missing keyword
00905. 00000 - "missing keyword"
*Cause:
*Action:
Error at Line: 21 Column: 1
EDIT:
Finished code below, changed a few expressions and conditions.
SELECT
S.SALENO,
SD.SERIALSTART,
SD.SERIALEND,
SDA.LABEL,
USR.USERNAME,
WH.NAME
FROM
ITR_SALE S
INNER JOIN
ITR_SALEDETAIL SD ON S.ID = SD.SALEID
INNER JOIN
ITR_ORDERSTATUS ODS ON SD.ID = ODS.ID
INNER JOIN
ITR_WAREHOUSE WH ON ODS.ID = WH.NAME
INNER JOIN
ITR_USER USR ON WH.ID = USR.USERNAME
INNER JOIN
ITR_STOCKDETAIL SDA ON USR.ID = SDA.LABEL
WHERE 'DATE' BETWEEN '2016-01-01' AND '2016-12-31'
AND S.STATUSID = '4';`
Use proper join syntax. Edit. Need to remove parenthesis from last line or user IN clause.
SELECT
S.SALENO,
SD.SERIALSTART,
SD.SERIALEND,
SDT.LABEL,
USR.USERNAME,
WH.NAME
FROM
ITR_SALE S INNER JOIN ITR_SALEDETAIL SD ON S.ID = SD.SALENO
INNER JOIN ITR_SALEDETAIL SD ON S.ID = SD.SALENO
INNER JOIN ITR_WAREHOUSE WH ON SD.ID = WH.NAME
INNER JOIN ITR_ORDER ODR ON WH.ID = ODR.STATUSID
INNER JOIN ITR_USER USR ON ODR.ID = USR.USERNAME
INNER JOIN ITR_STOCKDETAIL STD ON USR.ID = SDT.LABEL
WHERE S.LASTSTATUSCHANGETIME
BETWEEN '2016-01-01 00:00:00' AND '2016-12-31 23:59:59'
AND STATUSID = 'COMPLETED';

Percentile_Cont function throwing error

I have this query where I am trying to introduce a non-static value into PERCENTILE_CONT:
SELECT perf2.REVIEW_PERIOD
, PERCENTILE_CONT(goalsASP.GOAL*.01) WITHIN GROUP (ORDER BY AVG_AMT ASC) ast75
FROM repDB.TBL_PERFORMANCE perf2 JOIN
pz.CATEGORY C on perf2.DEPTCAT = C.id JOIN
repDB.TBL_GOALS_MATRIX goalsASP ON C.NAME = goalsASP.DIMENSION_Y
and perf2.REVIEW_PERIOD = goalsASP.SNAP_NAME
and goalsASP.DIMENSION_X = 'asp'
GROUP BY perf2.REVIEW_PERIOD
The error thrown is:
ORA-30497: Argument should be a constant or a function of expressions in GROUP BY.
30497. 00000 - "Argument should be a constant or a function of expressions in GROUP BY."
This is in a view, it was working fine when goalsASP.GOAL*.01 was .75 and I have a stored procedure where feeding a column as an argument works just fine so I'm kind of at a loss for what I'm doing wrong here.
Got it. It's not so much a problem of Percentile_Cont, it's a problem of correct grouping.
To troubleshoot I isolated goalsASP.GOAL
SELECT perf2.REVIEW_PERIOD
, goalsASP.GOAL
FROM repDB.TBL_PERFORMANCE perf2 JOIN
pz.CATEGORY C on perf2.DEPTCAT = C.id JOIN
repDB.TBL_GOALS_MATRIX goalsASP ON C.NAME = goalsASP.DIMENSION_Y
and perf2.REVIEW_PERIOD = goalsASP.SNAP_NAME
and goalsASP.DIMENSION_X = 'asp'
GROUP BY perf2.REVIEW_PERIOD
Then it became obvious that I needed to also group by goalsASP.GOAL.
So, then, the answer is:
SELECT perf2.REVIEW_PERIOD
, PERCENTILE_CONT(goalsASP.GOAL*.01) WITHIN GROUP (ORDER BY AVG_AMT ASC) ast75
FROM repDB.TBL_PERFORMANCE perf2 JOIN
pz.CATEGORY C on perf2.DEPTCAT = C.id JOIN
repDB.TBL_GOALS_MATRIX goalsASP ON C.NAME = goalsASP.DIMENSION_Y
and perf2.REVIEW_PERIOD = goalsASP.SNAP_NAME
and goalsASP.DIMENSION_X = 'asp'
GROUP BY perf2.REVIEW_PERIOD,
goalsASP.GOAL
Kind of embarrassing that I didn't see that before, but tired eyes miss this stuff.

Oracle CONNECT BY and MAX

I am having difficulty integrating a MAX into a query and would greatly appreciate any help.
Basically what I'm trying to achieve is this: list a supervisor's supervisor's supervised employees along with their latest "day out" punch time.
The part I can't get right is the MAX(day out) part.
Here's the part I got so far that works fine:
SELECT EMPLOYEE.NUMBER,
EMPLOYEE.NAME,
S.NAME AS SUPERVISOR,
EMPLOYEE.HIRE_DATE
FROM EMPLOYEE
LEFT JOIN EMPLOYEE_NUMBER ON EMPLOYEE_NUMBER.NUMBER = EMPLOYEE.SUPERVISOR_NUMBER
LEFT JOIN EMPLOYEE S ON S.NUMBER = EMPLOYEE.SUPERVISOR_NUMBER
WHERE LEVEL =2
START WITH EMPLOYEE_NUMBER.USERID = (ID OF SUPERVISOR HERE)
CONNECT BY PRIOR EMPLOYEE.NUMBER = EMPLOYEE.SUPERVISOR_NUMBER
This part works and gives me the basic input that I need. However, I also need to list, for each employee, his/her lastest "day out" date.
Here's what I tried tried that didn't work:
SELECT EMPLOYEE.NUMBER,
EMPLOYEE.NAME,
S.NAME AS SUPERVISOR,
EMPLOYEE.HIRE_DATE,
MAX(EMPLOYEE_TIME.DATE_OUT)
FROM EMPLOYEE
LEFT JOIN EMPLOYEE_NUMBER ON EMPLOYEE_NUMBER.NUMBER = EMPLOYEE.SUPERVISOR_NUMBER
LEFT JOIN EMPLOYEE S ON S.NUMBER = EMPLOYEE.SUPERVISOR_NUMBER
LEFT JOIN EMPLOYEE_TIME ON EMPLOYEE_TIME.EMPLOYEE_NUMBER = EMPLOYEE.EMPLOYEE_NUMBER
WHERE LEVEL =2
START WITH EMPLOYEE_NUMBER.USERID = (ID OF SUPERVISOR HERE)
CONNECT BY PRIOR EMPLOYEE.NUMBER = EMPLOYEE.SUPERVISOR_NUMBER
GROUP BY
EMPLOYEE.NUMBER,
EMPLOYEE.NAME,
S.NAME,
EMPLOYEE.HIRE_DATE
HAVING MAX(EMPLOYEE_TIME.DATE_OUT) >= SYSDATE-60
It doesn't throw any error, it just keeps on processing forever. I'm guessing something must be looping but I can't figure it out.
Thanks for any help.
A slight change to your query in joining the time table, it need not be joined while CONNECT BY, instead separate it.
SELECT NUMBER,
EMPLOYEE_NAME,
SUPERVISOR,
HIRE_DATE,
MAX(TIME.DATE_OUT)
FROM
(SELECT NUMBER,
EMPLOYEE.NAME AS EMPLOYEE_NAME,
S.NAME AS SUPERVISOR,
EMPLOYEE.HIRE_DATE
FROM EMPLOYEE
LEFT JOIN EMPLOYEE_NUMBER ON EMPLOYEE_NUMBER.NUMBER = EMPLOYEE.SUPERVISOR_NUMBER
LEFT JOIN EMPLOYEE S ON S.NUMBER = EMPLOYEE.SUPERVISOR_NUMBER
WHERE LEVEL =2
START WITH EMPLOYEE_NUMBER.USERID = (ID OF SUPERVISOR HERE)
CONNECT BY PRIOR EMPLOYEE.NUMBER = EMPLOYEE.SUPERVISOR_NUMBER) EMP_SUP
INNER JOIN EMPLOYEE_TIME TIME
ON( EMP_SUP.NUMBER = TIME.NUMBER)
GROUP BY
NUMBER,
EMPLOYEE_NAME,
SUPERVISOR,
HIRE_DATE
HAVING MAX(DATE_OUT) >= SYSDATE-60

Writing SQL query for bids

How can I write a query for this? I'm not an expert to write this much of complex queries in SQL. I forgot to mention bid 3, 4 here.
Based on David's query, eliminating duplicate bids and restricting by check type.
SELECT
a.bid, min(a.time) checkin, ISNULL(min(b.time), '') checkout
FROM
myTable a
LEFT JOIN
myTable b ON a.bid = b.bid
WHERE
a.type = "Check In"
AND
b.type = "Check Out"
GROUP BY
a.bid
ORDER BY
a.time
SELECT
a.bid, a.time checkin, ISNULL(b.time, '') checkout
FROM
myTable a
LEFT JOIN
myTable b ON a.bid = b.bid AND b.type = 'Check Out'
WHERE
a.type = 'Check In'
ORDER BY
a.time
EDIT
In response to your comment, seeing as there are several records of the same bid, and you only want one record per bid in your output, you need to specify which records you want in your output. When there are more than one, how do you decide what value to pick? If you always want the earliest checkin and the latest checkout, you might do something like this:
SELECT
a.bid,
MIN(a.time) checkin,
ISNULL((SELECT
MAX(time)
FROM
myTable
WHERE
bid = a.bid
AND type = 'Check Out'), '') checkout
FROM
myTable a
WHERE
a.type = 'Check In'
GROUP BY
a.bid
If that's not exactly what you want; adjust the use of MIN and MAX to fit your needs.
This will find the minimum check in and check out times for each bid id.
select bid,
(select min(time) from table b where a.bid = b.bid and type = "Check In") as CheckIn,
(select min(time) from table c where a.bid = c.bid and type = "Check Out") as CheckOut
from table c
group by c.bid
I think you're looking for something like this:
SELECT
`bid`,
MAX(IF(`type` = 'Check In', `time`, NULL)) AS `CheckIn`,
MAX(IF(`type` = 'Check Out', `time`, NULL)) AS `CheckOut`
FROM `yourtable`
GROUP BY `bid`

Resources