How to use alias column name in oracle query - sql

I have a two table one is Mn_Fdd_Cong and another is test_t .Here i have to split a column value in table Mn_Fdd_Cong based on character underscore and take first part and join with second table. But in my query alias is not working
select regexp_substr(a.Ids, '[^_]+', 1, 1) as "Id" ,a.*,b.*
from Mn_Fdd_Cong a
left join test_t b on a.Id = b.Site_Id where b.G_VAL='U'

You can't use it that way; either extract "new" ID in a subquery (or a CTE) and then re-use it in "main" query, or - simpler - use it directly in JOIN operation.
I used simple substr + instr combination instead of regular expressions (performs better on large data sets).
select a.*, b.*
from md_fdd_cong a join test_t b on b.site_id = substr(a.ids, 1, instr(a.ids, '_') - 1)
where b.g_val = 'U'
Here's the 1st option I suggested (a CTE):
select x.*, b.*
from (select a.*,
substr(a.ids, 1, instr(a.ids, '_') - 1) id --> this is ID ...
from md_fdd_cong a
) x
join test_t b on b.site_id = x.id --> ... which is then used here (as "x.id")
where b.g_val = 'U';

You can't use an alias you define in your select in the join (logically, the join happens before the select). You could duplicate the calculation
select regexp_substr(a.Ids, '[^_]+', 1, 1) as "Id" ,a.*,b.*
from Mn_Fdd_Cong a
left join test_t b on regexp_substr(a.Ids, '[^_]+', 1, 1) = b.Site_Id
where b.G_VAL='U'
Or you could nest the calculation. Personally, I'd put the mn_fdd_cong manipulation into a common table expression (CTE). Note that if you put an identifier like Id in double-quotes, you're creating a case-sensitive identifier so subsequent references to it would need to use the same case-sensitive identifier and would need to use the double quotes.
with new_a as (
select regexp_substr(a.Ids, '[^_]+', 1, 1) as "Id" ,a.*
from Mn_Fdd_Cong a
)
select a.*, b.*
from new_a a
join test_t b on a."Id" = b.Site_Id
where b.G_VAL='U'

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

The right way to use aliases in SQL

I have question about SQL. Below I have query from order controller in Prestashop 1.6. The question is. Why I have two aliases for ps_orders ? Please check below query:
SELECT SQL_NO_CACHE SQL_CALC_FOUND_ROWS
a.`id_order`,
`reference`,
`total_paid_tax_incl`,
`payment`,
a.`date_add` AS `date_add`,
a.id_currency,
a.id_order AS id_pdf,
CONCAT(LEFT(c.`firstname`, 1), '. ', c.`lastname`) AS `customer`,
osl.`name` AS `osname`,
os.`color`,
IF(
(SELECT COUNT(id_customer)
FROM `ps_orders` so
WHERE so.id_customer = a.id_customer) = 1, "Tak", "Nie") AS first_order,
IF(
(SELECT so.id_order
FROM `ps_orders` so
WHERE so.id_customer = a.id_customer
AND so.id_order < a.id_order
LIMIT 1) > 0, 0, 1) AS NEW,
country_lang.name AS cname,
IF(a.valid, 1, 0) badge_success
FROM `ps_orders` a
LEFT JOIN `ps_customer` c ON (c.`id_customer` = a.`id_customer`)
LEFT JOIN `ps_address` address ON address.id_address = a.id_address_delivery
LEFT JOIN `ps_country` country ON address.id_country = country.id_country
LEFT JOIN `ps_country_lang` country_lang ON (country.`id_country` = country_lang.`id_country`
AND country_lang.`id_lang` = 6)
LEFT JOIN `ps_order_state` os ON (os.`id_order_state` = a.`current_state`)
LEFT JOIN `ps_order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state`
AND osl.`id_lang` = 6)
WHERE 1
ORDER BY a.`id_order` DESC
LIMIT 0, 50
Once I have a.id_order in another so.id_order. Maybe I am wrong but I thing that is the same ps_orders. First declaration is ps_orders so and the second ps_orders a ? Why someone use two aliases to the same table ?
General queries are like:
SELECT
A.SomeColumn
FROM
YourTable A
If you have subqueries then
SELECT
A.SomeColumn,
(SELECT SomeOtherColumn FROM AnotherTable) ColumnAlias
FROM
YourTable A
And if you have a subquery with the same table, you might want to use different aliases to distinguish them!
SELECT
A.SomeColumn,
(SELECT B.SomeColumn FROM YourTable B) ColumnAlias
FROM
YourTable A
Columns from tables referenced in subqueries cannot be referenced outside:
SELECT
A.SomeColumn,
(SELECT B.SomeOtherColumn FROM YourTable B) ColumnAlias,
B.SomeOtherColumn -- What table is B here? Outside scope!
FROM
YourTable A
But columns from the outside can be referenced inside!
SELECT
A.SomeColumn,
(SELECT B.SomeOtherColumn FROM YourTable B WHERE B.SomeOtherColumn = A.SomeColumn) ColumnAlias,
FROM
YourTable A
PD: I'm assuming in these examples that the subquery returns 1 row.
One alias is for the main query, and the other is used in the sub queries.
The main query and each subquery must use an alias since they both are referencing the same table as the main query.
That's the only way the sub query can relate to the records from the same table used in the main query - Just like when you do a self join - Once you have the same table (or view) more than once in your query, you must use different aliases for it.

Compare fields from different rows

First off I am using SQL Server.
I am joining a table on itself like in the example below:
SELECT t.theDate,
s.theDate,
t.bitField,
s.bitField,
t.NAME,
s.NAME
FROM table1 t
INNER JOIN table1 s ON t.NAME = s.NAME
If I take a random row (i.e. X) from the dataset produced.
Can I compare values in any field on row X to values in any field on row X-1 OR row X+1?
Example: I want to compare t.theDate on row 5 to s.theDate on row 4 or s.theDate on row 3.
Sample data looks like:
Desired results:
I want to pull all pairs of rows where the t.bitfield and s.bitfield are opposite and t.theDate and s.theDate are opposite.
From the image the would be row (3 & 4), (5 & 6), (7 & 8) ... etc.
I really appreciate any help!
Can it be done?
Varinant 1: It looks like you would like to use ranking function.
if objcet_id('tempdb..#TmpOrderedTable') is not null drop table #TmpOrderedTable
select *, row_number(order by columnlist, (select 0)) rn
into #TmpOrderedTable
from table1 t
select *
from #TmpOrderedTable t0
inner join #TmpOrderedTable tplus on t0.rn = tplus.rn + 1 -- next one
inner join #TmpOrderedTable tminus on t0.rn = tminus.rn - 1 -- previous one
Varinant 2:
To get scalar values you can use ranking function lag and lead. Or subquery.
Varinant 3:
You can use selfjoin, but you have to specify unique nonarbitary key if you don't want duplicates.
Varinant 4:
You can use apply.
Your question isn't too clear, so i hope it was your goal.
How about this?
WITH ts as (
SELECT t.theDate as theDate1, s.theDate as theDate2,
t.bitField as bitField1, s.bitField as bitField2,
t.NAME -- there is only one name
FROM table1 t INNER JOIN
table1 s
ON t.NAME = s.NAME
)
SELECT ts.*
FROM ts
WHERE EXISTS (SELECT 1
FROM ts ts2
WHERE ts2.name = ts.name AND
ts2.theDate1 = ts.theDate2 AND
ts2.theDate2 = ts.theDate1 AND
ts2.bitField1 = ts.bitField2 AND
ts2.bitField2 = ts.bitField1
);

How do I use a column in a single-row tables as a scalar?

Suppose I have a table tab1 with only one row and bigger tables big1 and big2.
How do I use a column in tab1 (which contains a single number) as a scalar, in, e.g.,
select a.foo * tab1.bar - b.quux
from big1 a join big2 b by big1.id = big2.id
Just do another join. It's only one row, so it's not expensive:
select a.foo * tab1.bar - b.quux
from big1 a join big2 b by big1.id = big2.id join tab1;
It's a bit of overkill, but you can use the distributed_map UDF in Brickhouse ( http://github.com/klout/brickhouse ) and create a map with only one key
insert overwrite directory 'mytab1'
select bar, 'value' from tab1;
add file mytab1;
select a.foo * array_index( map_keys( distributed_map( 'mytab1' ) ),0 ) - b.quux
from big1 a join big2 b on ( big1.id = big2.id )

ITVF with With-Statement possible?

IS it possible to return the table of a With-Statement from an inline-table valued function?
my With-Statement looks like this
WITH ret AS(
SELECT t.ID
FROM SelfReferencingTable
WHERE ID = #PartnerID
UNION ALL
SELECT t.ID
FROM (SelfReferencingTable) t INNER JOIN
ret r ON t.ParentID = r.ID
)
Yes, you can. You just have to place the common table expression (what you refer to as a WITH statement) in the appropriate place:
create function TT()
RETURNS TABLE
AS
RETURN (With Aardvark as (select * from sysobjects) --TODO - Remove *, use column names
select * from Aardvark)
;