Correct way to select from two tables in SQL Server with no common field to join on - sql

Back in the old days, I used to write select statements like this:
SELECT
table1.columnA, table2.columnA
FROM
table1, table2
WHERE
table1.columnA = 'Some value'
However I was told that having comma separated table names in the "FROM" clause is not ANSI92 compatible. There should always be a JOIN statement.
This leads to my problem.... I want to do a comparison of data between two tables but there is no common field in both tables with which to create a join. If I use the 'legacy' method of comma separated table names in the FROM clause (see code example), then it works perfectly fine. I feel uncomfortable using this method if it is considered wrong or bad practice.
Anyone know what to do in this situation?
Extra Info:
Table1 contains a list of locations in 'geography' data type
Table2 contains a different list of 'geography' locations
I am writing select statement to compare the distances between the locations. As far I know you cant do a JOIN on a geography column??

You can (should) use CROSS JOIN. Following query will be equivalent to yours:
SELECT
table1.columnA
, table2.columnA
FROM table1
CROSS JOIN table2
WHERE table1.columnA = 'Some value'
or you can even use INNER JOIN with some always true conditon:
FROM table1
INNER JOIN table2 ON 1=1

Cross join will help to join multiple tables with no common fields.But be careful while joining as this join will give cartesian resultset of two tables.
QUERY:
SELECT
table1.columnA
, table2,columnA
FROM table1
CROSS JOIN table2
Alternative way to join on some condition that is always true like
SELECT
table1.columnA
, table2,columnA
FROM table1
INNER JOIN table2 ON 1=1
But this type of query should be avoided for performance as well as coding standards.

A suggestion - when using cross join please take care of the duplicate scenarios. For example in your case:
Table 1 may have >1 columns as part of primary keys(say table1_id,
id2, id3, table2_id)
Table 2 may have >1 columns as part of primary keys(say table2_id,
id3, id4)
since there are common keys between these two tables (i.e. foreign keys in one/other) - we will end up with duplicate results. hence using the following form is good:
WITH data_mined_table (col1, col2, col3, etc....) AS
SELECT DISTINCT col1, col2, col3, blabla
FROM table_1 (NOLOCK), table_2(NOLOCK))
SELECT * from data_mined WHERE data_mined_table.col1 = :my_param_value

Related

does equi join return duplicate column

Consider following points:
As we know, inner join returns the duplicate column for which we have defined the joining condition.
And we know natural join it removes the duplicate.
I know we can use equi join:
select * from table1, table2 where id1=id2
or
select * from table1 join table2 on id1 = id2
I have confusion in this third point. I want to know what is the scenario in equi join what it returns? Does it return with duplicate column where we have defined the joining condition like inner join.
To answer titled question: Yes, if your query uses SELECT *. While your focus is on the JOIN clause, you are forgetting fundamentals about the SELECT clause in SQL.
By the way your #3 (your definition of equi join) is equivalent to #1 (inner join). In #3, the former using WHERE is the older, de-emphasized (ANSI-89) implicit join style and the latter using JOIN is the current, standard (ANSI-92) explicit join. Both return same results and should render same performance but readability arguably differs. See Explicit vs implicit SQL joins.
The reason you receive duplicate columns for these equi-join cases is the SELECT clause requests for all columns of all joined tables since you do not qualify the asterisk,*:
select * from table1 join table2 on id1 = id2
However, using asterisk alone is an abbreviated, convenience method but the recommended way is to explicitly control your resultset by selecting specific columns. This is crucial for application builds where column order and existence is required and helps in code readability and maintainability. See Why is SELECT * considered harmful?
Below are examples that can be used to avoid duplicate columns: qualifying the asterisks, subsetting/omiting columns, and even renaming/re-ordering columns with aliases .
-- ONLY table1 COLUMNS
select table1.* from table1 join table2 on id1 = id2
-- ONLY table2 COLUMNS
select table2.* from table1 join table2 on id1 = id2
-- SUBSET OF table1 AND table2 COLUMNS
select table1.Col1, table1.Col2, table1.Col3
, table2.Col4, table2.Col5, table2.Col6
from table1
join table2 on id1 = id2
-- RENAMED COLUMNS
select table1.Col1 as t1_col1, table1.Col2 as t1_col2, table1.Col3 as t1_col3
, table2.Col3 as t2_col3, table2.Col2 as t2_col2, table2.Col1 as t2_col1
from table1
join table2 on id1 = id2

Comparing two datasets SQL SSRS 2005

I have two datasets on two seperate servers. They both pull one column of information each.
I would like to build a report showing the values of the rows that only appear in one of the datasets.
From what I have read, it seems I would like to do this on the SQL side, not the reporting side; I am not sure how to do that.
If someone could shed some light on how that is possible, I would really appreciate it.
You can use the NOT EXISTS clause to get the differences between the two tables.
SELECT
Column
FROM
DatabaseName.SchemaName.Table1
WHERE
NOT EXISTS
(
SELECT
Column
FROM
LinkedServerName.DatabaseName.SchemaName.Table2
WHERE
Table1.Column = Table2.Column --looks at equalities, and doesn't
--include them because of the
--NOT EXISTS clause
)
This will show the rows in Table1 that don't appear in Table2. You can reverse the table names to find the rows in Table2 that don't appear in Table1.
Edit: Made an edit to show what the case would be in the event of linked servers. Also, if you wanted to see all of the rows that are not shared in both tables at the same time, you can try something as in the below.
SELECT
Column, 'Table1' TableName
FROM
DatabaseName.SchemaName.Table1
WHERE
NOT EXISTS
(
SELECT
Column
FROM
LinkedServerName.DatabaseName.SchemaName.Table2
WHERE
Table1.Column = Table2.Column --looks at equalities, and doesn't
--include them because of the
--NOT EXISTS clause
)
UNION
SELECT
Column, 'Table2' TableName
FROM
LinkedServerName.DatabaseName.SchemaName.Table2
WHERE
NOT EXISTS
(
SELECT
Column
FROM
DatabaseName.SchemaName.Table1
WHERE
Table1.Column = Table2.Column
)
You can also use a left join:
select a.* from tableA a
left join tableB b
on a.PrimaryKey = b.ForeignKey
where b.ForeignKey is null
This query will return all records from tableA that do not have corresponding records in tableB.
If you want rows that appear in exactly one data set and you have a matching key on each table, then you can use a full outer join:
select *
from table1 t1 full outer join
table2 t2
on t1.key = t2.key
where t1.key is null and t2.key is not null or
t1.key is not null and t2.key is null
The where condition chooses the rows where exactly one match.
The problem with this query, though, is that you get lots of columns with nulls. One way to fix this is by going through the columns one by one in the SELECT clause.
select coalesce(t1.key, t2.key) as key, . . .
Another way to solve this problem is to use a union with a window function. This version brings together all the rows and counts the number of times that key appears:
select t.*
from (select t.*, count(*) over (partition by key) as keycnt
from ((select 'Table1' as which, t.*
from table1 t
) union all
(select 'Table2' as which, t.*
from table2 t
)
) t
) t
where keycnt = 1
This has the additional column specifying which table the value comes from. It also has an extra column, keycnt, with the value 1. If you have a composite key, you would just replace with the list of columns specifying a match between the two tables.

SQL query, where = value of another table

I want to make a query that simply makes this, this may sound really dumb but i made a lot of research and couldn't understand nothing.
Imagine that i have two tables (table1 and table2) and two columns (table1.column1 and table2.column2).
What i want to make is basically this:
SELECT column1 FROM table1 where table2.column2 = '0'
I don't know if this is possible.
Thanks in advance,
You need to apply join between two talbes and than you can apply your where clause will do work for you
select column1 from table1
inner join table2 on table1.column = table2.column
where table2.columne=0
for join info you can see this
Reading this original article on The Code Project will help you a lot: Visual Representation of SQL Joins.
Find original one at: Difference between JOIN and OUTER JOIN in MySQL.
SELECT column1 FROM table1 t1
where exists (select 1 from table2 t2
where t1.id = t2.table1_id and t2.column2 = '0')
assuming table1_id in table2 is a foreign key refering to id of table1 which is the primary key
You don't have any kind of natural join between two tables.
You're asking for
Select Houses.DoorColour from Houses, Cars where Cars.AreFourWheelDrive = '1'
You'd need to think about why you're selecting anything from the first table, there must be a shared piece of information between tables 1 and 2 otherwise a join is pointless and probably dangerous.

how to select fields from different db's with the same table and field name

I have two databases, for argument sake lets call them db1 and db2. they are both structured exactly the same and both have a table called table1 which both have fields id and value1.
My question is how do I do a query that selects the field value1 for both tables linked by the same id???
You can prefix the table names with the database name to identify the two similarly named tables. You can then use that fully qualified table name to refer to the similarly named fields.
So, without aliases:
select db1.table1.id, db1.table1.value1, db2.table1.value1
from db1.table1 inner join db2.table1 on db1.table1.id = db2.table1.id
and with aliases
select t1.id, t1.value1, t2.value1
from db1.table1 as t1 inner join db2.table1 as t2 on t1.id = t2.id
You may also want to alias the selected columns so your select line becomes:
select t1.id as id, t1.value1 as value_from_db1, t2.value1 as value_from_db2
This is T-Sql, but I can't imagine mysql would be that much different (will delete answer if that's not the case)
SELECT
a.Value1 AS [aValue]
,b.Value1 AS [bValue]
FROM
db1.dbo.Table1 a
INNER JOIN db2.dbo.Table1 b
ON a.Id = b.Id
Try something such as this.
$dbhost="server_name";
$dbuser1="user1";
$dbpass1="password1";
$dbname1="database_I";
$dbname2="database_II";
$db1=mssql_connect($dbhost,$dbuser1,$dbpass1);
mssql_select_db($dbname1,$db1);
$query="SELECT ... FROM database_I.table1, database_II.table2 WHERE ....";
etc. Sorry if this does not help.
There is an easy way in sql. Extend your syntax for FROM clause, so instead of using select ... from tablename, use
select ... from database.namespace.tablename
The default namespace is dbo.
You could use a union select:
Simple example:
select "one" union select "two";
This will return 2 rows, the first row contains one and the 2nd row contains two. It is as if you are concatenating 2 sql quires, the only constant is that they both must return the same number of columns.
Multiple databases:
select * from client_db.users where id=1 union select * from master_db.users where id=1;
In this case both users databases must have the same number of columns. You said they have the same structure, so you shouldn't have a problem.

In SQL, a Join is actually an Intersection? And it is also a linkage or a "Sideway Union"?

I always thought of a Join in SQL as some kind of linkage between two tables.
For example,
select e.name, d.name from employees e, departments d
where employees.deptID = departments.deptID
In this case, it is linking two tables, to show each employee with a department name instead of a department ID. And kind of like a "linkage" or "Union" sideway".
But, after learning about inner join vs outer join, it shows that a Join (Inner join) is actually an intersection.
For example, when one table has the ID 1, 2, 7, 8, while another table has the ID 7 and 8 only, the way we get the intersection is:
select * from t1, t2 where t1.ID = t2.ID
to get the two records of "7 and 8". So it is actually an intersection.
So we have the "Intersection" of 2 tables. Compare this with the "Union" operation on 2 tables. Can a Join be thought of as an "Intersection"? But what about the "linking" or "sideway union" aspect of it?
You're on the right track; the rows returned by an INNER JOIN are those that satisfy the join conditions. But this is like an intersection only because you're using equality in your join condition, applied to columns from each table.
Also be aware that INTERSECTION is already an SQL operation and it has another meaning -- and it's not the same as JOIN.
An SQL JOIN can produce a new type of row, which has all the columns from both joined tables. For example: col4, col5, and col6 don't exist in table A, but they do exist in the result of a join with table B:
SELECT a.col1, a.col2, a.col3, b.col4, b.col5, b.col6
FROM A INNER JOIN B ON a.col2=b.col5;
An SQL INTERSECTION returns rows that are common to two separate tables, which must already have the same columns.
SELECT col1, col2, col3 FROM A
INTERSECT
SELECT col1, col2, col3 FROM B;
This happens to produce the same result as the following join:
SELECT a.col1, a.col2, a.col3
FROM A INNER JOIN B ON a.col1=b.col1 AND a.col2=b.col2 AND a.col3=b.col3;
Not every brand of database supports the INTERSECTION operator.
A join 'links' or erm... joins the rows from two tables. I think that's what you mean by 'sideways union' although I personally think that is a terrible way to phrase it. But there are different types of joins that do slightly different things:
An inner join is indeed an intersection.
A full outer join is a union.
This page on Jeff Atwood's blog describes other possibilities.
An Outer Join - is not related to - Union or Union All.
For example, a 'null' would not occur as a result of Union or Union All operation, but it results from an Outer Join.
INNER JOIN treats two NULLs as two different values. So, if you join based on a nullable column, and if both tables have NULL values in that column, then INNER JOIN will ignore those rows.
Therefore, to correctly retrieve all common rows between two tables, INTERSECT should be used. INTERSECT treats two NULLs as the same value.
Example(SQLite):
Create two tables with nullable columns:
CREATE TABLE Table1 (id INT, firstName TEXT);
CREATE TABLE Table2 (id INT, firstName TEXT);
Insert NULL values:
INSERT INTO Table1 VALUES (1, NULL);
INSERT INTO Table2 VALUES (1, NULL);
Retrieve common rows using INNER JOIN (This shows no output):
SELECT * FROM Table1 INNER JOIN Table2 ON
Table1.id=Table2.id AND Table1.firstName=Table2.firstName;
Retrieve common rows using INTERSECT (This correctly shows the common row):
SELECT * FROM Table1 INTERSECT SELECT * FROM Table2;
Conclusion:
Even though, many times both INTERSECT and INNER JOIN can be used to get the same results, they are not the same and should be picked depending on the situation.