Can I reference on an alias in Oracle? - sql

I have a query like this:
SELECT
ARUTORZS.ARUKOD,
ARUTORZS.ARUNEV,
(SELECT SUM(MENNYISEG)
FROM ((((STOREIS.KESZLET
LEFT OUTER JOIN STOREIS.THELY ON
THELY.TH=KESZLET.TH)
LEFT OUTER JOIN STOREIS.ZONA ON
ZONA.ZONAKOD=THELY.ZONA)
LEFT OUTER JOIN STOREIS.ARUTELEP ON
ARUTELEP.TH_KOD='P' AND
ARUTELEP.ARUKOD=KESZLET.ARUKOD)
LEFT OUTER JOIN STOREIS.RAKTAR ON
RAKTAR.RAKTAR=KESZLET.RKOD)
WHERE KESZLET.ARUKOD=ARUTORZS.ARUKOD ) AS keszlet,
ARUTELEP.RKOD,
ARUTELEP.ZONA_KOMISSIOS,
ARUTORZS.GYARTO_KOD,
UGYFEL.ORACLE_KOD,
UGYFEL.SZAML_NEV,
ARUTORZS.SULY,
**ARUTORZS.SULY*keszlet/1000 AS SULYKG,**
ARUTORZS.REL_LEJ,
ARUTORZS.GYUJTO,
ARUTORZS.RAKLAP_MENNY
FROM ((STOREIS.ARUTORZS
LEFT OUTER JOIN STOREIS.ARUTELEP ON
ARUTELEP.TH_KOD='P' AND
ARUTELEP.ARUKOD=ARUTORZS.ARUKOD)
LEFT OUTER JOIN STOREIS.UGYFEL ON
UGYFEL.UGYF_KOD=ARUTORZS.GYARTO_KOD)
WHERE ARUTELEP.RKOD>=100 AND ARUTELEP.RKOD<=199
The keszlet subquery works, but Ican't reference on its result in another column. How can I reference on the result of the keszlet subquery? I want to multiply it in another column.

Use a table expression.
For example:
select
x.*,
c * m as r
from (
select
a,
(select max(b) from t) as m,
c
from t
) x
The table expression produces a "named column" m that you can use in the main query in the expression c * m.

You can use your result from your subquery, but u have to use it as a table subquery.
Description
With table subqueries, the outer query treats the result of the
subquery as a table. You can only use these in the FROM clause.
So, your subquery goes after the FROM clause and you can make a new join like this:
SELECT your_result_value * --do what you want...
FROM
(SELECT SUM(MENNYISEG) as YOUR_RESULT_VALUE, PK --your_primary_key
FROM ((((STOREIS.KESZLET
LEFT OUTER JOIN STOREIS.THELY ON
THELY.TH=KESZLET.TH)
LEFT OUTER JOIN STOREIS.ZONA ON
ZONA.ZONAKOD=THELY.ZONA)
LEFT OUTER JOIN STOREIS.ARUTELEP ON
ARUTELEP.TH_KOD='P' AND
ARUTELEP.ARUKOD=KESZLET.ARUKOD)
LEFT OUTER JOIN STOREIS.RAKTAR ON
RAKTAR.RAKTAR=KESZLET.RKOD)
WHERE KESZLET.ARUKOD=ARUTORZS.ARUKOD ) keszlet
JOIN "your_tables" ON keszlet.PK = "another_PK"
--and so on...

Related

How to do an OUTER join with a spatial join in BigQuery to be able to get a count value of 0 where there is no intersection?

I'm doing a fairly conventional point/polygon spatial join in order to determine the number of points that fall in each polygon. The result (from the left join) includes all of the polygons + the count where there is an intersection. But it doesn't return the polygon + 0 or null where there is no intersection. I'd like to still have the polygon geometry as it looks better on a map (vs. just a missing area).
WITH
geoidandcount AS(
SELECT
a.geo_id,
COUNT(b.latitude) AS count
FROM
`polygon_dataset` a
LEFT OUTER JOIN -- ERROR
`point_dataset` b
ON
st_contains(a.the_geom,
ST_GEOGPOINT(b.longitude,
b.latitude))
GROUP BY
a.geo_id )
SELECT
a.*,
b.the_geom,
a.count,
FROM
geoidandcount a
JOIN
`polygon_dataset` b
USING
(geo_id)
I had to do the CTE as you can't group by geography.
Yes, BigQuery cannot yet optimize geospatial OUTER JOIN, which is why you get this error. The workaround is to do geospatial INNER JOIN followed by OUTER JOIN on some unique ID in the OUTER table.
To demonstrate on simpler example, let's take this part of the query:
SELECT
a.geo_id,
b.latitude
FROM
`polygon_dataset` a
LEFT OUTER JOIN -- ERROR
`point_dataset` b
ON
st_contains(a.the_geom, ST_GEOGPOINT(b.longitude, b.latitude))
Assuming geo_id is unique in the left table, this can be replaced with
SELECT
a.geo_id,
c.latitude
FROM
`polygon_dataset` a
LEFT OUTER JOIN
(
SELECT
a.geo_id
b.latitude
FROM
`polygon_dataset` a
JOIN
`point_dataset` b
ON
st_contains(a.the_geom, ST_GEOGPOINT(b.longitude, b.latitude))
) c
ON a.geo_id = c.geo_id
Here the count would be NULL when nothing is matched on the right, so let's use COALESCE(count, 0) to get 0.
The full query will be something like
SELECT
a.geo_id,
a.the_geom,
COALESCE(c.count, 0) AS count
FROM
`polygon_dataset` a
LEFT OUTER JOIN
(
SELECT
a.geo_id
COUNT(b.latitude) as count
FROM
`polygon_dataset` a
JOIN
`point_dataset` b
ON
st_contains(a.the_geom, ST_GEOGPOINT(b.longitude, b.latitude))
GROUP BY
geo_id
) c
ON a.geo_id = c.geo_id

SQL query with 2 counts and 2 left outer joins

Im trying to show all columns from my t1_elem table and join 2 columns in which I use COUNT.
I used query:
SELECT p.*,COUNT(t4_id) as ile_publikacji, COUNT(t7_id) as ile_fitow
FROM t1_elem p
LEFT OUTER JOIN t4_autorzy ON p.t1_id=t4_autorzy.t4_t1_id
LEFT JOIN t7_pliki ON p.t1_id=t7_pliki.t7_t1_id
GROUP BY t1_id
But the results are bad. What I'm doing wrong?
Probably you have multiple matches. As stated, the two counts will be the same. The simplest solution is probably to use distinct:
SELECT p.*, COUNT(DISTINCT t4_id) as ile_publikacji, COUNT(DISTINCT t7_id) as ile_fitow
FROM t1_elem p LEFT JOIn
t4_autorzy
ON p.t1_id = t4_autorzy.t4_t1_id LEFT JOIN
t7_pliki
ON p.t1_id=t7_pliki.t7_t1_id
GROUP BY t1_id

use Inner Join in SQL

I want to join two tables and then I want to join this result with another table
but it doesn't work
select * from
(
(select SeId,FLName,Company from Sellers) s
inner join
(select SeId,BIId from BuyInvoices) b
on s.SeId=b.SeId
) Y
inner join
(select * from BuyPayments) X
on Y.BIId=X.BIId
thanks
In most databases, your syntax isn't going to work. Although parentheses are allowed in the FROM clause, they don't get their own table aliases.
You can simplify the JOIN. This is a simpler way to write the logic:
select s.SeId, s.FLName, s.Company, bp.*
from Sellers s inner join
BuyInvoices b
on s.SeId = b.SeId inner join
BuyPayments bp
on bp.BIId = b.BIId;

SQL: Proper JOIN Protocol

I have the following tables with the following attributes:
Op(OpNo, OpName, Date)
OpConvert(OpNo, M_OpNo, Source_ID, Date)
Source(Source_ID, Source_Name, Date)
Fleet(OpNo, S_No, Date)
I have the current multiple JOIN query which gives me the results that I want:
SELECT O.OpNo AS Op_NO, O.OpName, O.Date AS Date_Entered, C.*
FROM Op O
LEFT OUTER JOIN OpConvert C
ON O.OpNo = C.OpNo
LEFT OUTER JOIN Source D
ON C.Source_ID = D.Source_ID
WHERE C.OpNo IS NOT NULL
The problem is this. I need to join the Fleet table on the previous multiple JOIN statement to attach the relevant S_No to the multiple JOIN table. Would I still be able to accomplish this using a LEFT OUTER JOIN or would I have to use a different JOIN statement? Also, which table would I JOIN on?
Please note that I am only familiar with LEFT OUTER JOINS.
Thanks.
I guess in your case you could use INNER JOIN or LEFT JOIN (which is the same thing as LEFT OUTER JOIN in SQL Server.
INNER JOIN means that it will only return records from other tables only if there are corresponding records (based on the join condition) in the Fleet table.
LEFT JOIN means that it will return records from other tables even if there are no corresponding records (based on the join condition) in the Fleet table. All columns from Fleet will return NULL in this case.
As for which table to join, you should really join the table that makes more logical sense based on your data structure.
Yes, you can use all tables mentioned before in your join conditions. Actually, JOINS (no matter of INNER, LEFT OUTER, RIGHT OUTER, CROSS, FULL OUTER or whatever) are left- associative, i. e. they are implicitly evaluated as if they would have been included in parentheses from the left as follows:
FROM ( ( ( Op O
LEFT OUTER JOIN OpConvert C
ON O.OpNo = C.OpNo
)
LEFT OUTER JOIN Source D
ON C.Source_ID = D.Source_ID
)
LEFT OUTER JOIN Fleet
ON ...
)
This is similar to how + or - would implicitly use parentheses, i. e.
2 + 3 - 4 - 5
is evaluated as
(((2 + 3) - 4) - 5)
By the way: If you use C.OpNo IS NOT NULL, then the LEFT OUTER JOIN Source D is treated as if it were an INNER JOIN, as you are explicitly removing all the "OUTER" rows.

SQL joining three tables, join precedence

I have three tables: R, S and P.
Table R Joins with S through a foreign key; there should be at least one record in S, so I can JOIN:
SELECT
*
FROM
R
JOIN S ON (S.id = R.fks)
If there's no record in S then I get no rows, that's fine.
Then table S joins with P, where records is P may or may not be present and joined with S.
So I do
SELECT
*
FROM
R
JOIN S ON (S.id = R.fks)
LEFT JOIN P ON (P.id = S.fkp)
What if I wanted the second JOIN to be tied to S not to R, like if I could use parentheses:
SELECT
*
FROM
R
JOIN (S ON (S.id = R.fks) JOIN P ON (P.id = S.fkp))
Or is that already a natural behaviour of the cartesian product between R, S and P?
All kinds of outer and normal joins are in the same precedence class and operators take effect left-to-right at a given nesting level of the query. You can put the join expression on the right side in parentheses to cause it to take effect first. Remember that you will have to move the ON clauses around so that they stay with their joins—the join in parentheses takes its ON clause with it into the parentheses, so it now comes textually before the other ON clause which will be after the parentheses in the outer join statement.
(PostgreSQL example)
In
SELECT * FROM a LEFT JOIN b ON (a.id = b.id) JOIN c ON (b.ref = c.id);
the a-b join takes effect first, but we can force the b-c join to take effect first by putting it in parentheses, which looks like:
SELECT * FROM a LEFT JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);
Often you can express the same thing without extra parentheses by moving the joins around and changing the direction of the outer joins, e.g.
SELECT * FROM b JOIN c ON (b.ref = c.id) RIGHT JOIN a ON (a.id = b.id);
When you join the third table, your first query
SELECT
*
FROM
R
JOIN S ON (S.id = R.fks)
is like a derived table to which you're joining the third table. So if R JOIN S produces no rows, then joining P will never yield any rows (because you're trying to join to an empty table).
So, if you're looking for precedence rules then in this case it's just set by using LEFT JOIN as opposed to JOIN.
However, I may be misunderstanding your question, because if I were writing the query, I would swap S and R around. eg.
SELECT
*
FROM
S
JOIN R ON (S.id = R.fks)
The second join is tied to S as you explicity state JOIN P ON (P.id = S.fkp) - no column from R is referenced in the join.
with a as (select 1 as test union select 2)
select * from a left join
a as b on a.test=b.test and b.test=1 inner join
a as c on b.test=c.test
go
with a as (select 1 as test union select 2)
select * from a inner join
a as b on a.test=b.test right join
a as c on b.test=c.test and b.test=1
Ideally, we would hope that the above two queries are the same. However, they are not - so anybody that says a right join can be replaced with a left join in all cases is wrong. Only by using the right join can we get the required result.