Can someone tell me how to convert Oracle (+) as joins in snowflakes is there any feasible way to convert.
I have a very complex 1k line SQL script which needs has 30+ (+) operators as joins.
Could anyone please help me
You can convert Oracle's outer join syntax to ANSI syntax. So it will be compatible with Snowflake and rest of the world (Even Oracle supports ANSI join syntax). You should re-write them manually but it's not a hard work:
Oracle:
SELECT d.department_name,
e.employee_name
FROM departments d, employees e
WHERE d.department_id = e.department_id (+)
AND d.department_id >= 30
ORDER BY d.department_name, e.employee_name;
ANSI
SELECT d.department_name,
e.employee_name
FROM departments d
LEFT OUTER JOIN employees e ON d.department_id = e.department_id
WHERE d.department_id >= 30
ORDER BY d.department_name, e.employee_name;
You can find explanations on that page (for left/right/outer joins):
https://oracle-base.com/articles/misc/sql-for-beginners-joins#left-outer-join
Snowflake supports the (+) operator according to the WHERE clause documentation.
Related
I'm trying to do this in a SQL Server CE database, but the database engine keeps reporting errors.
SELECT C.guid, C.name, C.updated,
C.hddsize, C.hddavailable, C.hddfree,
C.ramsize, C.profiles, C.cpu,
(SELECT COUNT(D.id) AS numprogs
FROM ComputerData AS D
WHERE D.computer_id = C.id) AS numprograms
FROM Computers AS C;
I've been told SQL Server CE supports subqueries. Is there something I'm doing wrong?
The limitation in SQL CE is that it does not support subqueries that return a scalar value. Subqueries that return a set are parsed fine.
The subquery in the join in Grayson's answer returns a set, so it should work. Sometimes a scalar subquery cannot be avoided in a join condition. By using 'IN' instead of '=', the parser can be tricked.
See my answer to this question.
My only experiences in queries are with MySQL, but hopefully it is similar enough.
Your query looks strange to me because your subquery is in the SELECT clause. I have never seen that before... but apparently it is supported in MySQL. Usually the subquery comes in the after a FROM or LEFT JOIN or JOIN.
Your example is simple enough that you could implement it with a LEFT JOIN:
SELECT C.guid, ..., COUNT(distinct D.id) as numprogs
FROM Computers AS C
LEFT JOIN ComputerData as D ON D.computer_id = C.id
In this case, LEFT JOIN is the correct type of join to use because even if there is no matching record in the D table for a particular C record, your result set will still contain that C record and numprogs will just be zero, as you would expect.
If you really want to use a subquery, try this:
SELECT C.guid, ..., S.numprogs
FROM Computers AS C
LEFT JOIN
(SELECT computer_id, COUNT(*) as numprogs
FROM ComputerData GROUP BY computer_id) AS S
ON C.id=S.computer_id
I suggest simplifying your query to get it to be the simplest possible query that should work, but doesn't work. Then tell us the specific error message that your database engine is returning.
Edit: I loooked in the MySQL chapter about subqueries and it seems like you should try removing the "as numprograms" clause after your subquery... maybe you don't get any choice about the naming of the column that comes out of the subquery after you've already composed the subquery.
How can I limit an inner join or a subquery that it only selects one row? As it seems I can't use 'top 1' in my Sybase version (Sybase version: Adaptive Server Enterprise/15.5/EBF 19902) in subqueries.
Example
select * from A a
inner join B b on a.id = b.Aid
whereat table B has two records linked to table A (same Aid). But I'd like to join only one of these records.
I tried to replace the inner join with a subquery and using top 1, but this is not allowed.
I found a solution here: https://www.periscopedata.com/blog/4-ways-to-join-only-the-first-row-in-sql.html
select * from A a
inner join (select * from B b where b.Aid in (select min(Aid) from B group by Aid) )
as b on b.Aid = a.id
Came across this post while going from "Sybase ASE doesn't support ROW_NUMBER()" to "TOP is not allowed in subqueries", to how tf do Sybase engineers expect us to limit a subquery result to 1 record? All solutions I've seen rely on min/max, but I haven't seen anything supporting a "ORDER BY" type of sorting.
So a simple
ROW_NUMBER() OVER (ORDER BY t.SEQUENCE, t.FROMDATE, t.FROMTIME)
becomes
select MYVALUE
from (SELECT someExpression as MYVALUE,
RIGHT(CONVERT(VARCHAR,1000000+fs.SEQUENCE), 6) || CONVERT(VARCHAR,t.FROMDATE, 23) || CONVERT(VARCHAR,t.FROMTIME) as SORTKEY
FROM MY_TABLE t)
having SORTKEY = MIN(SORTKEY)
which is rather ugly, using all sorts of hacks to support string-sorting of the ORDER BY fields. As this will be used in subqueries, table alias scoping will mean that table joins need to be replicated.
The only alternative I can think of is a cursor with a break-condition so only the first row is processed, but that'll slow down things considerably.
I ran into a problem with my T-SQL query. I have warehouse database, and I want to add currency exchange rates to my transactions, to see them in EUR and USD.
To do that, I am using Europe Central bank currency rates.
My query looks like this:
SELECT
Companys.Companys_name,
Warehouse_oper.Pavad_num,
[Items]![Quantity]*[Items]![Price] AS Expr1,
[Items]![Quantity]*[Items]![Price]*[Exchange_rates]![USD] AS Expr2
FROM
(Companys
LEFT JOIN
(Exchange_rates
RIGHT JOIN
Warehouse_oper ON Exchange_rates.Date = Warehouse_oper.Date)
ON Companys.Companys_num_d_b = Warehouse_oper.Companys_nr_d_b)
LEFT JOIN
Items ON Warehouse_oper.Warehouse_oper_num_d_b = Items.Warehouse_oper_num_d_b;
Sorry if its hard to understand, because I translated all variables to English.
Anyways this query works fine, if LEFT JOIN (Exchange_rates RIGHT JOIN Warehouse_oper ON Exchange_rates.Date = Warehouse_oper.Date, but bank does not provide them on holidays, so on those dates I have NULL values.
How can I edit this query (I know it's messy, but it's from Access) to SELECT most recent available date?
I tried:
LEFT JOIN
(Exchange_rates RIGHT JOIN Warehouse_oper ON
(SELECT TOP 1 Exchange_rates.Date FROM Exchange_rates WHERE
Exchange_rates.Date <= Warehouse_oper.Date) = Warehouse_oper.Date)
but with no success.
I'm practicing using AdventureWorks and here's the question:
How many Sales Orders (Headers) used Vista credit cards in October 2002
SELECT * FROM Sales.SalesOrderHeader --a
SELECT * FROM Sales.CreditCard --b
SELECT
SUM(a.OrderDate), b.CardType
FROM
[Sales].[CreditCard] b
LEFT OUTER JOIN
[Sales].[SalesOrderHeader] a
I'm not sure how to write this query. I'm new to SQL and this is my first JOIN. Eyes are red...thanks
There are several issues:
You cannot sum dates. You have to use count here.
You must not use an outer join here. Use an inner join. The reason is that you only want SalesOrderHeaders that also have a corresponding CreditCard
You forgot the where clause
A join needs an on condition
select count(*) from
CreditCard cc inner join SalesOrderHeader so on cc.Id = so.CreditCardId
where cc.CardType = 'Visa' and so.OrderDate between '2002-10-01' and '2002-10-31'
I guessed the names of the foreign key fields cc.Id and so.CreditCardId because you didn't indicate this piece of information.
I have a sql server query that returns rows more than I expected:
select
b.isbn, l.lend_no, s.first_name
from
dbo.books b, dbo.lending l, dbo.students s
where
(l.act between '4/16/2013' and '4/16/2013')
and (l.stat ='close')`
I want to do is get the isbn, lend_no and student name that book returned date is between given dates and lend status is closed , my lending table has only 2 lending that returned on given date but query give me 304 rows
Your current query gets the cartesian product from the three tables causing to retrieve unexpected result. You need to define the relationship or how the tables should be join, example
select b.isbn, l.lend_no, s.first_name
from dbo.books b
INNER JOIN dbo.lending l
ON c.Colname = l.ColName -- << define condition here
INNER JOIN dbo.students s
ON ...... -- << define condition here
where l.act between '4/16/2013' and '4/16/2013' and
l.stat ='close'
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
You're not definining any join conditions between the tables, so you'll get a cartesian product.
Try something like this instead:
SELECT
b.isbn, l.lend_no, s.first_name
FROM
dbo.books b
INNER JOIN
dbo.lending l ON l.Book_id = b.Book_id -- just guessing here
INNER JOIN
dbo.students s ON l.student_id = s.student_id -- just guessing here
WHERE
l.act BETWEEN '20130416' AND '20130416'
AND l.stat = 'close'
Define the join conditions as needed - I don't know your tables, you'll have to find out what columns link the two tables respectively.
I also used the proper ANSI JOIN syntax - don't just list a bunch of tables separated by a comma, that's been kicked out of the SQL standards over 20 years ago (SQL 1992).
Also: I would always use the ISO-8601 date format YYYYMMDD to be safe - this is the only format that works on all versions of SQL Server and with all language, regional and dateformat settings.
Your FROM clause isn't doing what you expect it to. By specifying the tables that way you are doing a full join which is giving you a cartesian product. You need to be using the proper table join syntax.
This is a great explanation of table joins: http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html