T-SQL: Wild Card as table name alias in select statement possible? - sql

This is more of a curiosity than an actual applied question. Say you have a statement with multiple joins such as:
SELECT
a.name,
b.salary,
c.x
FROM
[table1] a
INNER JOIN [table2] b
ON a.key = b.key
INNER JOIN [table3] c
ON b.key = c.key
Now, say you were to make several more joins to other tables whose schema was unfamiliar, however you know:
the keys on which to make the join
that several of those tables has a column with the the name 'x'.
Is it possible to select 'x' from all tables that contain it, without explicitly referring to the table alias. So it would ave a similar results as this (if it were possible)
SELECT
a.name,
b.salary,
*.x
...

No this isn't possible.
You can use a.* to get all columns from a but it is not valid to use a wildcard as the table name.

#Martin Smith is correct that you can't use *.x and refer to columns from multiple tables. There is however a way to write a query that shows all columns x from tables where they exist without breaking if one or more of the tables do not have such column. It's a rather complicated way that (mis)uses scope resolution.
Lets say that some of the tables (b and d in the example) have a column named x, while some others (c here) do not have such column. Then you can replace INNER joins with CROSS APPLY and LEFT joins with OUTER APPLY and a query with:
SELECT
a.name,
a.salary,
b.x AS bx,
'WITHOUT column x' AS cx,
d.x AS dx
FROM
a
INNER JOIN b
ON a.aid = b.aid
LEFT JOIN c
ON a.aid = c.aid
LEFT JOIN d
ON a.aid = d.aid ;
would be written as:
SELECT
a.name,
a.salary,
bx,
cx,
dx
FROM
( SELECT a.*,
'WITHOUT column x' AS x
FROM a
) a
CROSS APPLY
( SELECT x AS bx
FROM b
WHERE a.aid = b.aid
) b
OUTER APPLY
( SELECT x AS cx
FROM c
WHERE a.aid = c.aid
) c
OUTER APPLY
( SELECT x AS dx
FROM d
WHERE a.aid = d.aid
) d ;
Tested at SQL-Server 2008: SQL-Fiddle

Related

Oracle SQL: How to convert multiple (+) WHERE clauses to LEFT JOINS? [duplicate]

This question already has answers here:
Oracle "(+)" Operator
(4 answers)
Closed last month.
I'm trying to convert some Oracle SQL code to regular SQL and am having trouble with the numerous variables in the SELECT statement, tables in the FROM statement, and (+) WHERE statements.
I have looked through similar posts but all provide simple examples with just 2 variables, 2 tables, and 1 (+) WHERE statement. I'm not sure how to apply what I'm seeing from the other forum posts to multiple variables, tables, and (+) WHERE statements.
SELECT
a.ID,
c.var1,
d.var2
FROM a, b, c, d, x, y
WHERE a.ID(+) = b.ID
AND c.var1(+) = b.var1
AND x.id(+) = y.id;
I tried to convert all the (+) WHERE statements to LEFT JOINs as shown below. I did 3 LEFT JOINS, one for each (+) WHERE statement:
SELECT
a.ID,
c.var1,
d.var2
FROM a, b, c, d, x, y
WHERE b.ID in
(SELECT b.ID
FROM b
LEFT JOIN a
ON a.ID = b.ID)
The query:
SELECT a.ID,
c.var1,
d.var2
FROM a, b, c, d, x, y
can be rewritten using ANSI-join syntax as:
SELECT a.ID,
c.var1,
d.var2
FROM a
CROSS JOIN b
CROSS JOIN c
CROSS JOIN d
CROSS JOIN x
CROSS JOIN y
If you add in the WHERE clause then WHERE c.var1(+) = b.var1 converts the CROSS JOIN to a LEFT OUTER JOIN from b to c. Similarly for the other join conditions.
Which gives you:
SELECT a.ID,
c.var1,
d.var2
FROM b
LEFT OUTER JOIN a ON a.ID = b.ID
LEFT OUTER JOIN c ON c.var1 = b.var1
CROSS JOIN d
CROSS JOIN y
LEFT OUTER JOIN x ON x.id = y.id;
fiddle

Compare table one value with two different tables in postgresql

There are three tables, A,B and C having common columns(name and number)
Table A have 10 records(say x) which can be only from table B(say, y) and table C(say, z) (like, x = y+z).
In table A, there are some records whose value is 0 (zero)
I need to compare those zero value based records using column = name, with other two tables.
And check the column "number" for the same "name" is also zero (0) in table B and table C?
I tried to write the below sample query to test on my small set of 3 tables data- but for some reasons I am not able to get all the 10 records as a result?
SELECT a.name,a.number as A_number, b.number as B_number, c.number as C_number
from A a, B b, C c
WHERE a.name = b.name
The above query gives me data as follows in the sqlfiddle-
http://sqlfiddle.com/#!2/57f86/1
In the above data- theres no record name="hello"
Can anyone please correct me where I am going wrong? and how to get the exact result? I need all the records from Table A. I know if I use left join it will populate all the left table data even if no match.
Possibilities: Table A having records, some may be present in table B
and some in table C, but not on both.
I think this is what you want:
SELECT a.*, b.number as bnumber, c.number as cnumber
from a left outer join
b
on a.name = b.name left outer join
c
on a.name = c.name
where a.number = 0;
By the way, here is a Postgres SQL Fiddle.
It's been over 20 years since the JOIN keyword was added to SQL. Use it:
select
a.name,
a.number as A_number,
b.number as B_number,
c.number as C_number
from A a
left join B b on a.name = b.name
left join C c on a.name = c.name
where a.number = 0
The key here is the use of left join, which allows all rows in table A to be returned, even if there are no matching rows in the other tables.
If you want to just display true/false if the number is zero in the other tables, do this:
select
a.name,
a.number as A_number,
(b.number = 0 and c.number = 0) as zero_elsewhere
from A a
left join B b on a.name = b.name
left join C c on a.name = c.name
where a.number = 0
When you wrote WHERE a.name = b.name, that restricted the records returned from table A to only those that also exist in table B. This is not equivalent to a left join. If you used only a WHERE statement you would need to do:
WHERE ((a.name = b.name) OR (b.name is NULL))
AND
((a.name = c.name) OR (c.name is NULL))
In the comments and other answers, they have been using LEFT JOIN which is easier to write and read. I suggest you adopt that style as it is widely accepted.

How to use oracle outer join with a filter where clause

If i write a sql:
select *
from a,b
where a.id=b.id(+)
and b.val="test"
and i want all records from a where corresponding record in b does not exist or it exists with val="test", is this the correct query?
You're much better off using the ANSI syntax
SELECT *
FROM a
LEFT OUTER JOIN b ON( a.id = b.id and
b.val = 'test' )
You can do the same thing using Oracle's syntax as well but it gets a bit hinkey
SELECT *
FROM a,
b
WHERE a.id = b.id(+)
AND b.val(+) = 'test'
Note that in both cases, I'm ignoring the c table since you don't specify a join condition. And I'm assuming that you don't really want to join A to B and then generate a Cartesian product with C.
Move the condition into the JOIN clause and use the ANSI standard join pattern.
SELECT NameYourFields,...
FROM A
LEFT OUTER JOIN B
ON A.ID = B.ID
AND B.VAL = 'test'
INNER JOIN C
ON ...
A LEFT OUTER JOIN is one of the JOIN operations that allow you to specify a join clause. It preserves the unmatched rows from the first (left) table, joining them with a NULL row in the shape of the second (right) table.
So you can do as follows :
SELECT
FROM a LEFT OUTER JOIN b
ON a.id = b.id
--Note that you have used double quote "test" which is not used for varchar in SQL you should use single quote 'test'
AND b.val = 'test';
SELECT * FROM abc a, xyz b
WHERE a.id = b.id
AND b.val = 'test'

Ambiguous Column Reference with an AS alias

I am unsure as to how to resolve an ambiguous column reference when using an alias.
Imagine two tables, a and b that both have a name column. If I join these two tables and alias the result, I do not know how to reference the name column for both tables. I've tried out a few variants, but none of them work:
Attempt 1
SELECT a.name, b.name
FROM (a INNER JOIN b ON a.id = b.id) AS x
This doesn't work as a and b are out of scope.
Attempt 2
SELECT x.a.name, x.b.name
FROM (a INNER JOIN b ON a.id = b.id) AS x
SQL syntax doesn't work like that.
Attempt 3
SELECT x.name, x.name
FROM (a INNER JOIN b ON a.id = b.id) AS x
That's just plain ambiguous!
I'm all out of ideas - any help would be much appreciated.
don't enclose it with parenthesis since (a INNER JOIN b ON a.id = b.id) is not a complete query.
SELECT a.name AS A_Name,
b.name AS B_Name
FROM a INNER JOIN b
ON a.id = b.id
or (assuming) if you have longer tables names and you want to make it short,
SELECT a.name AS A_Name,
b.name AS B_Name
FROM longTableNameA a
INNER JOIN longTableNameB b
ON a.id = b.id

Is it possible to do a 3 table join in MS-Access?

I try to do a 3-table join in Access and it will not work. Is it possible?
I once had a problem when I tried
select
x,
y
from
A inner join
B on k=l inner join
C on f=g
This didn't work. But it works with parantheses:
select
x,
y
from (
A inner join
B on k=l ) inner join
C on f=g
All the various types of multi-table joins that are available in other flavour of SQL are permitted in MS-Access/Jet. For example, here's a straight three-table hierarchical example (a bit more real-world than the other answers here):
SELECT
x.FirstName,
x.Surname,
r.RegionName,
c.CountryName
FROM
(Customer x LEFT JOIN Region r
ON r.ID=x.RegionID)
LEFT JOIN Country c
ON c.ID=r.CountryID
Or did you want to know how to do it using the Visual Designer in MS-Access?
Yes, it's possible:
Select *
From A, B, C
Where A.a = B.b
And A.c = C.c
or
Select *
From A, B, C
Where A.a = B.b
And B.c = C.c
Access can do most types of joins (apart from a full outer) I wonder with your 3 table join if you are doing an ambiguous outer join? Have a look at this KB article for an explanation
support.microsoft.com/kb/124937