How to write an SQL query to combine two already-ordered tables horizontally with different columns? - sql

I have two tables which I would like to place side-by-side exactly as they are. For example,
tableOne tableTwo
columnOne | columnTwo | columnThree columnI | columnII | columnIII
The data in the two tables do not need to be related whatsoever -- the tables have the same row count -- and the data is already sorted in the two tables. Basically, I would like to do a full outer join on the two tables without an on operator.
How can I do this in a SQL query?

Well, you do want an ON operator - you just seem to want it to work automatically, which won't happen.
If you're saying Row 1 of tableOne maps to Row 1 of tableTwo, then you need to add a row column to each table and then join on it.
If you don't specify a join condition, you'll do a cross join that joins every row from tableOne to every row in tableTwo, which obviously isn't what you're looking for.
So do something like this:
select * from
(select *, row_number() over (order by 1) as RN from tableOne) a
inner join (select *, row_number() over (order by 1) as RN from tableTwo) b
on a.RN = b.RN

Related

Select data from multiple table without join sql

I have 2 SQL table.Table A and Table B. Both of this table have 10000 records respectively.
In Table A have 3 Column=>
ColumnA,ColumnB,ColumnC
In Table B have 3 Column=>
ColumnD,ColumnE,ColumnF
My Requirement is to select ColumnA and ColumnD with their original record(10000).
My question is how can I select only ColumnA and ColumnD.
The first problem is I cant join this two table because this two table stands as separately.
The second problem is I cant Union this two table because my requirement is to get Two column but when I union, I only get one column with combining two column.
You could create an on-the-fly join column via ROW_NUMBER, and then join on that:
WITH cte1 AS (
SELECT ColumnA, ROW_NUMBER() OVER (ORDER BY ColumnA) rn
FROM TableA
),
cte2 AS (
SELECT ColumnD, ROW_NUMBER() OVER (ORDER BY ColumnD) rn
FROM TableB
)
SELECT t1.ColumnA, t2.ColumnD
FROM cte t1
INNER JOIN cte t2
ON t1.rn = t2.rn;
Of course, this would just pair the 10K records using the arbitrary orderings in the A and D columns. If you have some specific logic for how these two columns should be paired up, then let us know. The bottom line is that you can't easily get away from the concepts of join or union to bring these two columns together.

Different way of writing this SQL query with partition

Hi I have the below query in Teradata. I have a row number partition and from that I want rows with rn=1. Teradata doesn't let me use the row number as a filter in the same query. I know that I can put the below into a subquery with a where rn=1 and it gives me what I need. But the below snippet needs to go into a larger query and I want to simplify it if possible.
Is there a different way of doing this so I get a table with 2 columns - one row per customer with the corresponding fc_id for the latest eff_to_dt?
select cust_grp_id, fc_id, row_number() over (partition by cust_grp_id order by eff_to_dt desc) as rn
from table1
Have you considered using the QUALIFY clause in your query?
SELECT cust_grp_id
, fc_id
FROM table1
QUALIFY ROW_NUMBER()
OVER (PARTITION BY cust_grp_id
ORDER BY eff_to_dt desc)
= 1;
Calculate MAX eff_to_dt for each cust_grp_id and then join result to main table.
SELECT T1.cust_grp_id,
T1.fc_id,
T1.eff_to_dt
FROM Table1 AS T1
JOIN
(SELECT cust_grp_id,
MAX(eff_to_dt) AS max_eff_to_dt
FROM Table
GROUP BY cust_grp_id) AS T2 ON T2.cust_grp_id = T1.cust_grp_id
AND T2.max_eff_to_dt = T1.eff_to_dt
You can use a pair of JOINs to accomplish the same thing:
INNER JOIN My_Table T1 ON <some criteria>
LEFT OUTER JOIN My_Table T2 ON <some criteria> AND T2.eff_to_date > T1.eff_to_date
WHERE
T2.my_id IS NULL
You'll need to sort out the specific criteria for your larger query, but this is effectively JOINing all of the rows (T1), but then excluding any where a later row exists. In the WHERE clause you eliminate these by checking for a NULL value in a column that is NOT NULL (in this case I just assumed some ID value). The only way that would happen is if the LEFT OUTER JOIN on T2 failed to find a match - i.e. no rows later than the one that you want exist.
Also, whether or not the JOIN to T1 is LEFT OUTER or INNER is up to your specific requirements.

SQL MS Access Summing Results Based on Two Table Criteria

I've been asked to find if totals from one table exceed a certain value. However the identifier I need to group these is stored in another table. So I've figured how to isolate what I need and then copy into excel. However I do understand the principle of summing in SQL, as I've made my own queries that look like this:
SELECT * FROM
(SELECT ID, SUM(Table1.Amount) AS Subtotal FROM Table1 WHERE LineNumber = 1 GROUP BY ID) AS a, Table2 AS b
WHERE a.ID = b.ID
AND a.Subtotal > b.Threshold
In this case, the totals I need to sum all have the same LineNumber from the original table (Table1) so it's easy to compare to a value in a different table. What I want to do is be able to is join a subquery back to the original table, then GROUPBY the identifier and sum from the other table, adding a criteria that the original ID from table one must be a duplicate:
SELECT * FROM
((Table1 as t
INNER JOIN
(SELECT ID FROM Table1
GROUP BY ID HAVING COUNT(ID) >1) as b
ON t.ID = b.ID
Joining criteria back to the original table, I need to do this because the table I need to sum doesn't contain ID,
INNER JOIN Table2 as c
ON t.ID2 = c.ID2
WHERE c.LineNumber = 4
This is where I'm stuck. I want to sum all the LineNumber = 4 for each ID. Again, I had to join using ID2 because ID1 isn't in Table2
Perhaps I'm making this too complicated? Any suggestions would be welcome
Thanks!

Joining on 2 tables but only selecting rows from one of the tables

I have 2 tables with identical names and schema. I would like to join on them, but only select rows from one of the tables. What is a good way to do this? The below query selects the rows from both tables, but I just want table a2 from the other DB.
select a.fkey_id, a2.fkeyid_id, a.otherthing, a2.otherthing from mytable a
inner join otherdb.dbo.mytable a2 on a.fkey_id=a2.fkey_id
I tried using left outer join but since the schemas are identical between the 2 tables this doesn't seem to work.
EDIT: I am only including the "a" table columns in the select to get an idea of what values the rows are returning. I just don't want any rows returned from "a", so I'd like to filter those rows out somehow.
Just take out the references to "a2" columns from the select list.
select a.fkey_id, a.otherthing from mytable a
inner join otherdb.dbo.mytable a2 on a.fkey_id=a2.fkey_id
OR
select a.* from mytable a
inner join otherdb.dbo.mytable a2 on a.fkey_id=a2.fkey_id
Which begs the questions on why you're joining to the other table if you don't want data from it. Is this a filtering method? If so, it would better performance-wise to do an exists.
select a.* from mytable a
WHERE EXISTS (
SELECT 1
FROM otherdb.dbo.mytable a2
WHERE a.fkey_id=a2.fkey_id)
select a.fkey_id
, a.otherthing
from mytable a
WHERE EXISTS (SELECT 1
FROM otherdb.dbo.mytable a2
WHERE a.fkey_id=a2.fkey_id)

How do I limit the number of rows returned by this LEFT JOIN to one?

So I think I've seen a solution to this however they are all very complicated queries. I'm in oracle 11g for reference.
What I have is a simple one to many join which works great however I don't need the many. I just want the left table (the one) to just join any 1 row which meets the join criteria...not many rows.
I need to do this because the query is in a rollup which COUNTS so if I do the normal left join I get 5 rows where I only should be getting 1.
So example data is as follows:
TABLE 1:
-------------
TICKET_ID ASSIGNMENT
5 team1
6 team2
TABLE 2:
-------------
MANAGER_NAME ASSIGNMENT_GROUP USER
joe team1 sally
joe team1 stephen
joe team1 louis
harry team2 ted
harry team2 thelma
what I need to do is join these two tables on ASSIGNMENT=ASSIGNMENT_GROUP but only have 1 row returned.
when I do a left join I get three rows returned beaucse that is the nature of hte left join
If oracle supports row number (partition by) you can create a sub query selecting where row equals 1.
SELECT * FROM table1
LEFT JOIN
(SELECT *
FROM (SELECT *,
ROW_NUMBER()
OVER(PARTITION BY assignmentgroup ORDER BY assignmentgroup) AS Seq
FROM table2) a
WHERE Seq = 1) v
ON assignmet = v.assignmentgroup
You could do something like this.
SELECT t1.ticket_id,
t1.assignment,
t2.manager_name,
t2.user
FROM table1 t1
LEFT OUTER JOIN (SELECT manager_name,
assignment_group,
user,
row_number() over (partition by assignment_group
--order by <<something>>
) rnk
FROM table2) t2
ON ( t1.assignment = t2.assignment_group
AND t2.rnk = 1 )
This partitions the data in table2 by assignment_group and then arbitrarily ranks them to pull one arbitrary row per assignment_group. If you care which row is returned (or if you want to make the row returned deterministic) you could add an ORDER BY clause to the analytic function.
I think what you need is to use GROUP BY on the ASSIGNMENT_GROUP field.
http://www.w3schools.com/sql/sql_groupby.asp
In MySQL you could just GROUP BY ASSIGNMENT and be done. Oracle is more strict and refuses to just choose (in an undefined way) which values of the three rows to choose. That means all returned columns need to be part of GROUP BY or be subject to an aggregat function (COUNT, MIN, MAX...)
You can of course choose to just don't care and use some aggregat function on the returned columns.
select TICKET_ID, ASSIGNMENT, MAX(MANAGER_NAME), MAX(USER)
from T1
left join T2 on T1.ASSIGNMENT=T2.ASSIGNMENT_GROUP
group by TICKET_ID, ASSIGNMENT
If you do that I would seriously doubt that you need the JOIN in the first place.
MySQL could also help with GROUP_CONCAT in the case that you want a string concatenation of group values for a column (humans often like that), but with Oracle that is staggeringly complex.
Using a subquery as already suggested is an option, look here for an example. It also allows you to sort the subquery before selecting the top row.
In Oracle, if you want 1 result, you can use the ROWNUM statement to get the first N values of a query e.g.:
SELECT *
FROM TABLEX
WHERE
ROWNUM = 1 --gets the first value of the result
The problem with this single query is that Oracle never returns the data in the same order. So, you must oder your data before use rownum:
SELECT *
FROM
(SELECT * FROM TABLEX ORDER BY COL1)
WHERE
ROWNUM = 1
For your case, looks like you only need 1 result, so your query should look like:
SELECT *
FROM
TABLE1 T1
LEFT JOIN
(SELECT *
FROM TABLE2 T2 WHERE T1.ASSIGNMENT = T2.ASSIGNMENT_GROUP
AND
ROWNUM = 1) T3 ON T1.ASSIGNMENT = T3.ASSIGNMENT_GROUP
you can use subquery - select top 1