Oracle to T-SQL conversion. How can I make this work? - sql

Having trouble converting Oracle syntax to T-SQL. Trying to convert the following statement:
SELECT ORIG.*
,V.COUNTRY_COMMON_NAME
FROM
(SELECT O.*
,LC.LOCAL_COUNCIL
,LC.REGIONAL_COUNCIL
FROM ES_W_ORG_DIM_INIT O
LEFT JOIN ES_W_ORG_DIM_INIT CNTR ON (O.RSC_CNTR_ORG_ID = CNTR.ORG_ID)
LEFT JOIN ES_W_LCL_CNCL_BASE LC ON (TO_CHAR(O.STK_DIST_UNIT_NUMBER) =
TRIM(LC.UNITNUMBER))
WHERE O.ORG_TYPE_ID IN (7,8)
UNION
SELECT O.*
,LC.LOCAL_COUNCIL
,LC.REGIONAL_COUNCIL
FROM ES_W_ORG_DIM_INIT O
LEFT JOIN ES_W_ORG_DIM_INIT CNTR ON (O.RSC_CNTR_ORG_ID = CNTR.ORG_ID)
LEFT JOIN ES_W_LCL_CNCL_BASE LC ON (TO_CHAR(O.UNIT_NUMBER) =
TRIM(LC.UNITNUMBER))
WHERE O.ORG_TYPE_ID IN (5,6)
UNION
SELECT O.*
,NULL AS LOCAL_COUNTCIL
,NULL AS REGIONAL_COUNCIL
FROM ES_W_ORG_DIM_INIT O
WHERE O.ORG_TYPE_ID IN (60,61)
) ORIG
LEFT JOIN DW_ERSDB_ORG_ADDR_VW V ON (ORIG.ORG_ID = V.ORG_ID AND
V.ORG_ADDRESS_TYPE_ID = 1)
Attempted conversion:
WITH ORIG AS(
SELECT O.*
,LC.LOCAL_COUNCIL
,LC.REGIONAL_COUNCIL
FROM DSS_ERS_STAGE.ES_ORG_DIM O
LEFT JOIN DSS_ERS_STAGE.ES_ORG_DIM CNTR ON (O.RSC_CNTR_ORG_ID = CNTR.ORG_ID)
LEFT JOIN DSS_ERS_STAGE.ES_W_LCL_CNCL_BASE LC ON (CONVERT(VARCHAR,
O.STK_DIST_UNIT_NUMBER) = RTRIM(LTRIM(LC.UNITNUMBER)))
WHERE O.ORG_TYPE_ID IN (7,8)
UNION
(SELECT O.*
,LC.LOCAL_COUNCIL
,LC.REGIONAL_COUNCIL
FROM DSS_ERS_STAGE.ES_ORG_DIM O
LEFT JOIN DSS_ERS_STAGE.ES_ORG_DIM CNTR ON (O.RSC_CNTR_ORG_ID = CNTR.ORG_ID)
LEFT JOIN DSS_ERS_STAGE.ES_W_LCL_CNCL_BASE LC ON (CONVERT(VARCHAR,
O.UNIT_NUMBER) = RTRIM(LTRIM(LC.UNITNUMBER)))
WHERE O.ORG_TYPE_ID IN (5,6)
UNION
SELECT O.*
,NULL AS LOCAL_COUNCIL
,NULL AS REGIONAL_COUNCIL
FROM DSS_ERS_STAGE.ES_ORG_DIM O
WHERE O.ORG_TYPE_ID IN (60,61)
))
SELECT ORIG.*, V.COUNTRY_COMMON_NAME
FROM ORIG
LEFT JOIN DSS_ERS_STAGE.DW_ERSDB_ORG_ADDR_VW V ON (ORIG.ORG_ID = V.ORG_ID
AND
V.ORG_ADDRESS_TYPE_ID = 1)
*Just a note that the schemas specified are required in the target database
SQL Server error:
Msg 8156, Level 16, State 1, Line 1
The column 'LOCAL_COUNCIL' was specified multiple times for 'ORIG'.
Any ideas on how I can engineer this to make it work in SQL Server?

Jamie mentioned this in a comment but I'll try to explain in a bit more detail. For purposes of illustration, suppose I have the following two very simple tables.
create table CouncilA (LOCAL_COUNCIL int);
create table CouncilB (LOCAL_COUNCIL int);
insert CouncilA values (1);
insert CouncilB values (1);
SQL Server does allow you to query a result set that has non-unique column names. For instance, the following is legal:
select *
from
CouncilA A
inner join CouncilB B on A.LOCAL_COUNCIL = B.LOCAL_COUNCIL;
It produces the following result set:
LOCAL_COUNCIL LOCAL_COUNCIL
1 1
However, the documentation for common table expressions explicitly states:
Duplicate names within a single CTE definition are not allowed.
So if I try to wrap my earlier query like this, as you've done in your attempted conversion:
with CTE as
(
select *
from
CouncilA A
inner join CouncilB B on A.LOCAL_COUNCIL = B.LOCAL_COUNCIL
)
select * from CTE;
Then I get the error message that you're seeing:
Msg 8156, Level 16, State 1, Line 7
The column 'LOCAL_COUNCIL' was specified multiple times for 'CTE'.
Incidentally, the same is true for a sub-SELECT:
select * from
(
select *
from
CouncilA A
inner join CouncilB B on A.LOCAL_COUNCIL = B.LOCAL_COUNCIL
) X;
Result:
Msg 8156, Level 16, State 1, Line 13
The column 'LOCAL_COUNCIL' was specified multiple times for 'X'.
The error message you see refers to ORIG, which is the name of your CTE, so the definition of that CTE has multiple columns called LOCAL_COUNCIL, which presumably means that your ES_W_ORG_DIM_INIT table has a column called LOCAL_COUNCIL. Make sure your column names are unique within your CTE and you should be okay.

Related

SQL ORA-00904: invalid identifier - join issue

have a problem with my query:
select Sources.dataset.name setName, x.element_name Commodity_Is, y.element_name Provider_Is
from meta.object_meta_v x, meta.object_meta_v y
join dw.load_set2_curve on x.object_id = dw.load_set2_curve.curve_id
join Sources.dataset on Sources.dataset.id = dw.load_set2_curve.load_set_id
where dw.load_set2_curve.curve_id in (
select max(curve_id) sample_curve_id from dw.load_Set2_curve
group by load_set_id
)
and (meta.object_meta_v.attribute = 'Provider' or meta.object_meta_v.attribute = 'Commodity');
the error is on the line:
join dw.load_set2_curve on x.object_id = dw.load_set2_curve.curve_id
I know why, because, according to this article 'https://stackoverflow.com/questions/10500048/invalid-identifier-on-oracle-inner-join' - "Looks like you cannot refer to an outer table alias in the join condition of the inner query." Unfortunately, I don't know how to find a workaround as I am looking for two different records (Commodity_is and Provider_is) from the same table in my query (with aliases 'x' and 'y').
Do you have any hints?
Your problem is that you are not using the table aliases in the SELECT, ON and WHERE clauses and are trying to refer to identifiers as schema.table.column and, in some cases that is ambiguous and you need to use table_alias.column.
Additionally, you are trying to mix legacy comma joins with ANSI joins (which does work but the comma joins need to be last, not first, so its easier just to use ANSI joins all the way through):
select ds.name setName,
x.element_name Commodity_Is,
y.element_name Provider_Is
from meta.object_meta_v x
CROSS JOIN meta.object_meta_v y
INNER JOIN dw.load_set2_curve lsc
ON x.object_id = lsc.curve_id
INNER JOIN Sources.dataset ds
ON ds.id = lsc.load_set_id
where lsc.curve_id in (
select max(curve_id) sample_curve_id
from dw.load_Set2_curve
group by load_set_id
)
and ( x.attribute = 'Provider'
or y.attribute = 'Commodity');
Which, for the sample data:
CREATE TABLE meta.object_meta_v (object_id, element_name, attribute) AS
SELECT 1, 'A', 'Provider' FROM DUAL UNION ALL
SELECT 2, 'B', 'Commodity' FROM DUAL;
CREATE TABLE dw.load_set2_curve (curve_id, load_set_id) AS
SELECT 1, 100 FROM DUAL UNION ALL
SELECT 2, 200 FROM DUAL;
CREATE TABLE sources.dataset (id, name) AS
SELECT 100, 'DS1' FROM DUAL UNION ALL
SELECT 200, 'DS2' FROM DUAL;
Outputs:
SETNAME
COMMODITY_IS
PROVIDER_IS
DS1
A
B
DS1
A
A
DS2
B
B
db<>fiddle here

Using Pivot to change Rows into Columns

I am resposting this and adding additional information. I am working on a SQL Query and using Pivot and running into an issue. The columns which I have in the Pivot Table actually show as row data and is repeated for each server.
WITH agg AS
(
select NodeID,
count(distinct cpuindex) as number_of_cpu,
case
when count(distinct cpuindex) < 8 THEN 1
else count(distinct cpuindex) / 8
end AS number_of_cores
from CPUMultiLoad_Detail
where nodeid in (select nodeid from nodesdata)
group by NodeID
)
SELECT * FROM (
SELECT cp.Environment, n.Caption,
cs.ComponentName,cs.ComponentStatisticData, cs.ErrorMessage,
agg.NodeID, agg.number_of_cpu, agg.number_of_cores, n.description
FROM APM_CurrentStatistics cs
INNER JOIN APM_Application app
ON cs.ApplicationID = app.ID
AND app.Name IN ('Oracle Database Licensing')
INNER JOIN NodesData n
ON cs.NodeID = n.NodeID
AND n.description NOT LIKE '%Windows%'
INNER JOIN NodesCustomProperties cp
ON cp.NodeID = n.NodeID
INNER JOIN agg
ON cs.NodeID = agg.NodeID
) t
PIVOT(
max(cs.ErrorMessage) FOR cs.ComponentName IN (
[Oracle Version],
[Oracle Partitioning],
[Oracle Tuning Pack],
[Diagnostic Pack],
[Real Application Clusters (RAC)])
) AS pivot_table;
Desired Output
I am getting this Error
Msg 107, Level 15, State 1, Line 30
The column prefix 'cs' does not match with a table name or alias name used in the query.
Msg 107, Level 15, State 1, Line 30
The column prefix 'cs' does not match with a table name or alias name used in the query.
Any help will be greatly appreciated.
Just take out the two cs. in this line
max(cs.ErrorMessage) FOR cs.ComponentName IN (
It treats the prior select statement like it has already run so those column names don't need to be disambiguated

INNER JOINING THE TABLE ITSELF GIVES No column name was specified for column 2

SELECT *
FROM
construction AS T2
INNER JOIN
(
SELECT project,MAX(report_date)
FROM construction
GROUP BY project
) AS R
ON T2.project=R.project AND T2.report_date=R.report_date
getting this error. plz help
No column name was specified for column 2 of 'R'
You need to add alias for MAX(report_date):
SELECT *
FROM construction AS T2
INNER JOIN
(
SELECT project,MAX(report_date) AS report_date
FROM construction
GROUP BY project
) AS R
ON T2.project = R.project
AND T2.report_date = R.report_date;
In SQL Server you can use syntax:
SELECT *
FROM construction AS T2
INNER JOIN
(
SELECT project,MAX(report_date)
FROM construction
GROUP BY project
) AS R(project, report_date)
ON T2.project = R.project
AND T2.report_date = R.report_date;
You should specific the MAX(report_date) with an alias report_date.
Because your table R have two columns project,MAX(report_date).
You are getting this error because you have not specified column name for inner query
You have to write your query as
SELECT *
FROM construction
INNER JOIN
(
SELECT project,MAX(report_date)"Max_ReportDate"
FROM construction
GROUP BY project
) Max_construction
ON construction.project = Max_construction .project
AND construction.report_date = Max_construction .Max_ReportDate

getting "No column was specified for column 2 of 'd'" in sql server cte?

I have this query, but its not working as it should,
with c as (select
month(bookingdate) as duration,
count(*) as totalbookings
from
entbookings
group by month(bookingdate)
),
d as (SELECT
duration,
sum(totalitems)
FROM
[DrySoftBranch].[dbo].[mnthItemWiseTotalQty] ('1') AS BkdQty
group by duration
)
select
c.duration,
c.totalbookings,
d.bkdqty
from
c
inner join d
on c.duration = d.duration
when I run this, I am getting
Msg 8155, Level 16, State 2, Line 1
No column was specified for column 2 of 'd'.
Can any one tell me what am I doing wrong?
Also, when I run this,
with c as (select
month(bookingdate) as duration,
count(*) as totalbookings
from
entbookings
group by month(bookingdate)
),
d as (select
month(clothdeliverydate),
SUM(CONVERT(INT, deliveredqty))
FROM
barcodetable
where
month(clothdeliverydate) is not null
group by month(clothdeliverydate)
)
select
c.duration,
c.totalbookings,
d.bkdqty
from
c
inner join d
on c.duration = d.duration
I get
Msg 8155, Level 16, State 2, Line 1
No column was specified for column 1 of 'd'.
Msg 8155, Level 16, State 2, Line 1
No column was specified for column 2 of 'd'.
You just need to provide an alias for your aggregate columns in the CTE
d as (SELECT
duration,
sum(totalitems) as sumtotalitems
FROM
[DrySoftBranch].[dbo].[mnthItemWiseTotalQty] ('1') AS BkdQty
group by duration
)
[edit]
I tried to rewrite your query, but even yours will work once you associate aliases to the aggregate columns in the query that defines 'd'.
I think you are looking for the following:
First one:
select
c.duration,
c.totalbookings,
d.bkdqty
from
(select
month(bookingdate) as duration,
count(*) as totalbookings
from
entbookings
group by month(bookingdate)
) AS c
inner join
(SELECT
duration,
sum(totalitems) 'bkdqty'
FROM
[DrySoftBranch].[dbo].[mnthItemWiseTotalQty] ('1') AS BkdQty
group by duration
) AS d
on c.duration = d.duration
Second one:
select
c.duration,
c.totalbookings,
d.bkdqty
from
(select
month(bookingdate) as duration,
count(*) as totalbookings
from
entbookings
group by month(bookingdate)
) AS c
inner join
(select
month(clothdeliverydate) 'clothdeliverydatemonth',
SUM(CONVERT(INT, deliveredqty)) 'bkdqty'
FROM
barcodetable
where
month(clothdeliverydate) is not null
group by month(clothdeliverydate)
) AS d
on c.duration = d.duration
I had a similar query and a similar issue.
SELECT
*
FROM
Users ru
LEFT OUTER JOIN
(
SELECT ru1.UserID, COUNT(*)
FROM Referral r
LEFT OUTER JOIN Users ru1 ON r.ReferredUserId = ru1.UserID
GROUP BY ru1.UserID
) ReferralTotalCount ON ru.UserID = ReferralTotalCount.UserID
I found that SQL Server was choking on the COUNT(*) column, and was giving me the error No column was specified for column 2.
Putting an alias on the COUNT(*) column fixed the issue.
SELECT
*
FROM
Users ru
LEFT OUTER JOIN
(
SELECT ru1.UserID, COUNT(*) AS -->MyCount<--
FROM Referral r
LEFT OUTER JOIN Users ru1 ON r.ReferredUserId = ru1.UserID
GROUP BY ru1.UserID
) ReferralTotalCount ON ru.UserID = ReferralTotalCount.UserID
A single with clause can introduce multiple query names by separating them with a comma but it's mandatory that every column has a name
In this case, the second query has a column without one:
as (SELECT
duration,
sum(totalitems) --**HERE IS A MISSING NAME**
FROM ...
That's all.
Because you are creatin a table expression, you have to specify the structure of that table, you can achive this on two way:
1: In the select you can use the original columnnames (as in your first example), but with aggregates you have to use an alias (also in conflicting names). Like
sum(totalitems) as bkdqty
2: You need to specify the column names rigth after the name of the talbe, and then you just have to take care that the count of the names should mach the number of coulms was selected in the query. Like:
d (duration, bkdqty)
AS (Select.... )
With the second solution both of your query will work!
Quite an intuitive error message - just need to give the columns in d names
Change to either this
d as
(
select
[duration] = month(clothdeliverydate),
[bkdqty] = SUM(CONVERT(INT, deliveredqty))
FROM
barcodetable
where
month(clothdeliverydate) is not null
group by month(clothdeliverydate)
)
Or you can explicitly declare the fields in the definition of the cte:
d ([duration], [bkdqty]) as
(
select
month(clothdeliverydate),
SUM(CONVERT(INT, deliveredqty))
FROM
barcodetable
where
month(clothdeliverydate) is not null
group by month(clothdeliverydate)
)
Just add an alias name as follows
sum(totalitems) as totalitems.
evidently, as stated in the parser response, a column name is needed for both cases. In either versions the columns of "d" are not named.
in case 1: your column 2 of d is sum(totalitems) which is not named. duration will retain the name "duration"
in case 2: both month(clothdeliverydate) and SUM(CONVERT(INT, deliveredqty)) have to be named
Msg 8155, Level 16, State 2, Line 1
No column was specified for column 1 of 'd'.
Msg 8155, Level 16, State 2, Line 1
No column was specified for column 2 of 'd'.
ANSWER:
ROUND(AVG(CAST(column_name AS FLOAT)), 2) as column_name

pass an outer selects row variable to inner select in oracle

How do you pass an outer selects row variable to inner select in oracle, here is a sample query ( other outer joins has been removed. This query will be loaded 1 time in life time of an application). This query works
select l5.HIERARCHY_ID,
(select wm_concat(isbn) isbns from (
select op.isbn from oproduct op
LEFT JOIN assignment ha on op.r.reference = ha.reference
where ha.hierarchy_id = '100589'))isbns
from level l5 where l5.gid = '1007500000078694'
but when I change the inner select's where clause
where ha.hierarchy_id = '100589'))isbns
to
where ha.hierarchy_id = l5.HIERARCHY_ID))isbns
I get the following error
ORA-00904: "L5"."HIERARCHY_ID": invalid identifier
You cannot pass the value of a 2nd level SELECT.
For example -
SELECT value1 -- 1st level select
FROM (
SELECT value2 -- 2nd level select
FROM (
SELECT value3 -- 3rd level select.
You can have values from the 1st level SELECT available for only the second level SELECT.
Similarly the values in the second level SELECT are only available to the 1st level SELECT and the 3rd level SELECT not beyond that.
I did something like this to fix the problem. There was one unnecessary select
select
l5.HIERARCHY_ID,
(
select
wm_concat(op.isbn)
from
oproduct op
LEFT JOIN assignment ha on op.r.reference = ha.reference
where ha.hierarchy_id = l5.HIERARCHY_ID
) ISBNS
from
level l5
where
l5.gid = '1007500000078694'
I think I am reading your SQL correctly - you want an outer join when the hierarchy ids match?
SELECT
l5.hierarchy_id,
op.isbns
FROM
LEVEL l5
LEFT OUTER JOIN
(SELECT
wm_concat (op.isbn) isbns,
ha.hierarch_id
FROM
oproduct op
LEFT JOIN
assignment ha
ON op.reference = ha.reference) op
ON l5.gid = op.hierarchy_id