SQL Server 2008 - need help merging 2 tables (cartesian) - sql

I have 2 tables that are not related at all and I need to put them together - one column per table. When I try the cartesian join, I end up with every combination:
SELECT Field1, Field2 FROM Table1, Table2
Result:
Table1.Field1 Table2.Field2
---------------------------
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
I need it to return side-by-side:
Table1.Field1 Table2.Field2
---------------------------
1 1
2 2
3 3
is this possible? Thanks in advance
EDIT
Table1.Table1IDs
----------------
1
2
3
4
5
Table2.Table2IDs
----------------
6
7
8
9
10
Desired output (into a temp table/select statement)
Table1.Table1IDs Table2.Table2IDs
------------------------------------
1 6
2 7
3 8
4 9
5 10
So that I can then do my insert into the actual table I need to do an insert:
INSERT INTO dbo.MTMObjects
SELECT Table1IDs, Table2IDs
FROM [temp table or solution]
ANSWER
Bluefeet gave me the idea to use temp tables with an identity column that i can then use to join. His is 'safer' because you aren't relying on SQL's good humor to sort both recordsets the same, but this might help the next guy:
DECLARE #tmp_Table1 TABLE(ID int IDENTITY(1,1) NOT NULL, TableID1 int NOT NULL)
DECLARE #tmp_Table2 TABLE(ID int IDENTITY(1,1) NOT NULL, TableID2 int NOT NULL)
INSERT INTO #tmp_Table1
OUTPUT INSERTED.Field1
SELECT * FROM Table1
INSERT INTO #tmp_Table2
OUTPUT INSERTED.Field2
SELECT * FROM Table2
OUTPUT
SELECT tmp1.Field1, tmp2.Field2
FROM #tmp_Table1 tmp1 INNER JOIN #tmp_Table2 tmp2 ON tmp2.ID = tmp1.ID
CHEERS!

You can try something like this using row_number(). This will force a relationship between the two tables based on the row_number:
select t1.col1, t2.col2
from
(
select col1, row_number() over(order by col1) rn
from table1
) t1
inner join
(
select col2, row_number() over(order by col2) rn
from table2
) t2
on t1.rn = t2.rn
See SQL Fiddle with Demo

if i understood ...the only you need is to add a filter in where clause
SELECT Field1, Field2 FROM Table1, Table2 WHERE Table1.Field1=Table2.Field2

You should probably change your final solution to use an outer join instead of inner join, in case the tables don't have exactly the same number of rows.

Related

Combine three columns from different tables into one row

I am new to sql and are trying to combine a column value from three different tables and combine to one row in DB2 Warehouse on Cloud. Each table consists of only one row and unique column name. So what I want to is just join these three to one row their original column names.
Each table is built from a statement that looks like this:
SELECT SUM(FUEL_TEMP.FUEL_MLAD_VALUE) AS FUEL
FROM
(SELECT ML_ANOMALY_DETECTION.MLAD_METRIC AS MLAD_METRIC, ML_ANOMALY_DETECTION.MLAD_VALUE AS FUEL_MLAD_VALUE, ML_ANOMALY_DETECTION.TAG_NAME AS TAG_NAME, ML_ANOMALY_DETECTION.DATETIME AS DATETIME, DATA_CONFIG.SYSTEM_NAME AS SYSTEM_NAME
FROM ML_ANOMALY_DETECTION
INNER JOIN DATA_CONFIG ON
(ML_ANOMALY_DETECTION.TAG_NAME =DATA_CONFIG.TAG_NAME AND
DATA_CONFIG.SYSTEM_NAME = 'FUEL')
WHERE ML_ANOMALY_DETECTION.MLAD_METRIC = 'IFOREST_SCORE'
AND ML_ANOMALY_DETECTION.DATETIME >= (CURRENT DATE - 9 DAYS)
ORDER BY DATETIME DESC)
AS FUEL_TEMP
I have tried JOIN, INNER JOIN, UNION/UNION ALL, but can't get it to work as it should. How can I do this?
Use a cross-join like this:
create table table1 (field1 char(10));
create table table2 (field2 char(10));
create table table3 (field3 char(10));
insert into table1 values('value1');
insert into table2 values('value2');
insert into table3 values('value3');
select *
from table1
cross join table2
cross join table3;
Result:
field1 field2 field3
---------- ---------- ----------
value1 value2 value3
A cross join joins all the rows on the left with all the rows on the right. You will end up with a product of rows (table1 rows x table2 rows x table3 rows). Since each table only has one row, you will get (1 x 1 x 1) = 1 row.
Using UNION should solve your problem. Something like this:
SELECT
WarehouseDB1.WarehouseID AS TheID,
'A' AS TheSystem,
WarehouseDB1.TheValue AS TheValue
FROM WarehouseDB1
UNION
SELECT
WarehouseDB2.WarehouseID AS TheID,
'B' AS TheSystem,
WarehouseDB2.TheValue AS TheValue
FROM WarehouseDB2
UNION
WarehouseDB3.WarehouseID AS TheID,
'C' AS TheSystem,
WarehouseDB3.TheValue AS TheValue
FROM WarehouseDB3
Ill adapt the code with your table names and rows if you tell me what they are. This kind of query would return something like the following:
TheID TheSystem TheValue
1 A 10
2 A 20
3 B 30
4 C 40
5 C 50
As long as your column names match in each query, you should get the desired results.

SQL Derby return middle of table

Say I have a table that looks something like this
COL1
1
1
1
2
2
3
3
3
3
4
5
5
6
6
7
7
With some other columns that are unimportant for this question. If I want to return all but the first two values from 4 how would I do this with derby?
Here is the expected output to clear up what I'm wanting
COL1
3
3
3
3
4
5
5
6
6
Thanks for the help, I'm not the best with SQL but I'm trying :)
try this...
SELECT t.*
FROM mytab t
INNER JOIN (SELECT MIN(COL1) AS VAL2
FROM mytab
WHERE COL1 NOT IN (SELECT MIN(COL1) FROM mytab)) x
ON t.COL1 > x.VAL2
working example at
http://www.datagloop.com/?USERNAME=DATAGLOOP/SO_DERBY&ACTION=LOGIN
Here is a solution that uses a temporary table that allows more flexibility, readability and also allows you to tune the parameters better.
The ROWID part of the queries is your position reference.
CREATE TEMP TABLE mycol_order
(COL1 INTEGER NOT NULL,
TOTAL_COLS INTEGER NOT NULL,
PRIMARY KEY (COL1));
INSERT INTO mycol_order
(COL1,TOTAL_COLS)
SELECT DISTINCT t1.COL1,
t2.total
FROM mytab t1,
(SELECT COUNT(DISTINCT COL1) AS total FROM mytab) t2
ORDER BY 1;
SELECT t.*
FROM mytab t
INNER JOIN mycol_order co
ON co.col1 = t.col1
AND co.ROWID > 2
AND co.ROWID < co.total_cols;
Also updated the working example at
working example at http://www.datagloop.com/?USERNAME=DATAGLOOP/SO_DERBY&ACTION=LOGIN

SQL query to get ID from multiple inputs

I'm not sure the title is clear, but this is the situation.
I have a table that looks like this:
ID inputID value
4 1 10
4 2 20
4 3 100
6 1 15
6 2 20
6 3 44
I have user input that gives me the values for inputID 1 and inputID 2, after which I want to get the ID to get the other information corresponding to that ID.
Example: If the user gives inputID(1)=10, inputID(2)=20, I want to get 4
Using simple AND statements don't solve this problem. I have asked already asked a few people, but I can't seem to solve this seemingly simple problem.
What about something like this?
SELECT t1.ID
FROM table t1
INNER JOIN table t2
ON t1.ID = t2.ID
WHERE
t1.inputID = 1 AND t1.value = #input1 AND
t2.inputID = 2 AND t2.value = #input2
select ID from T as T1
where inputID=1 and value=10
and EXISTS(select id from T where ID=T1.ID and inputID=2 and value=20)
Try this query:
Create Table #tmp ( Id int, inputId int, value int)
insert into #tmp values (4,1,10)
insert into #tmp values (4,2,20)
insert into #tmp values (4,3,100)
insert into #tmp values (6,1,15)
insert into #tmp values (6,2,20)
insert into #tmp values (6,3,44)
-- my query
Select top 1 id from
(Select id,count(id) as cnt from #tmp where (inputId=1 and value=10) OR (inputId=2 and value=20) Group by id) tbl
order by cnt desc
-- Scoregraphic's query
SELECT t1.ID
FROM #tmp t1
INNER JOIN #tmp t2
ON t1.ID = t2.ID
WHERE
t1.inputID = 1 AND t1.value = 10 AND
t2.inputID = 2 AND t2.value = 20
Drop table #tmp
On seeing the execution plan my query is takes overall 23% and ScoreGraphic's query takes 21%

How to combine results of two queries into a single dataset

I have two queries :
Queries Simplified excluding Joins
Query 1 : select ProductName,NumberofProducts (in inventory) from Table1.....;
Query 2 : select ProductName, NumberofProductssold from Table2......;
I would like to know how I can get an output as :
ProductName NumberofProducts(in inventory) ProductName NumberofProductsSold
The relationships used for getting the outputs for each query are different.
I need the output this way for my SSRS report .
(I tried the union statement but it doesnt work for the output I want to see. )
Here is an example that does a union between two completely unrelated tables: the Student and the Products table. It generates an output that is 4 columns:
select
FirstName as Column1,
LastName as Column2,
email as Column3,
null as Column4
from
Student
union
select
ProductName as Column1,
QuantityPerUnit as Column2,
null as Column3,
UnitsInStock as Column4
from
Products
Obviously you'll tweak this for your own environment...
I think you are after something like this; (Using row_number() with CTE and performing a FULL OUTER JOIN )
Fiddle example
;with t1 as (
select col1,col2, row_number() over (order by col1) rn
from table1
),
t2 as (
select col3,col4, row_number() over (order by col3) rn
from table2
)
select col1,col2,col3,col4
from t1 full outer join t2 on t1.rn = t2.rn
Tables and data :
create table table1 (col1 int, col2 int)
create table table2 (col3 int, col4 int)
insert into table1 values
(1,2),(3,4)
insert into table2 values
(10,11),(30,40),(50,60)
Results :
| COL1 | COL2 | COL3 | COL4 |
---------------------------------
| 1 | 2 | 10 | 11 |
| 3 | 4 | 30 | 40 |
| (null) | (null) | 50 | 60 |
How about,
select
col1,
col2,
null col3,
null col4
from Table1
union all
select
null col1,
null col2,
col4 col3,
col5 col4
from Table2;
The problem is that unless your tables are related you can't determine how to join them, so you'd have to arbitrarily join them, resulting in a cartesian product:
select Table1.col1, Table1.col2, Table2.col3, Table2.col4
from Table1
cross join Table2
If you had, for example, the following data:
col1 col2
a 1
b 2
col3 col4
y 98
z 99
You would end up with the following:
col1 col2 col3 col4
a 1 y 98
a 1 z 99
b 2 y 98
b 2 z 99
Is this what you're looking for? If not, and you have some means of relating the tables, then you'd need to include that in joining the two tables together, e.g.:
select Table1.col1, Table1.col2, Table2.col3, Table2.col4
from Table1
inner join Table2
on Table1.JoiningField = Table2.JoiningField
That would pull things together for you into however the data is related, giving you your result.
If you mean that both ProductName fields are to have the same value, then:
SELECT a.ProductName,a.NumberofProducts,b.ProductName,b.NumberofProductsSold FROM Table1 a, Table2 b WHERE a.ProductName=b.ProductName;
Or, if you want the ProductName column to be displayed only once,
SELECT a.ProductName,a.NumberofProducts,b.NumberofProductsSold FROM Table1 a, Table2 b WHERE a.ProductName=b.ProductName;
Otherwise,if any row of Table1 can be associated with any row from Table2 (even though I really wonder why anyone'd want to do that), you could give this a look.
Old question, but where others use JOIN to combine unrelated queries to rows in one table, this is my solution to combine unrelated queries to one row, e.g:
select
(select count(*) c from v$session where program = 'w3wp.exe') w3wp,
(select count(*) c from v$session) total,
sysdate
from dual;
which gives the following one-row output:
W3WP TOTAL SYSDATE
----- ----- -------------------
14 290 2020/02/18 10:45:07
(which tells me that our web server currently uses 14 Oracle sessions out of the total of 290 sessions; I log this output without headers in an sqlplus script that runs every so many minutes)
Load each query into a datatable:
http://www.dotnetcurry.com/ShowArticle.aspx?ID=143
load both datatables into the dataset:
http://msdn.microsoft.com/en-us/library/aeskbwf7%28v=vs.80%29.aspx
This is what you can do. Assuming that your ProductName column have common values.
SELECT
Table1.ProductName,
Table1.NumberofProducts,
Table2.ProductName,
Table2.NumberofProductssold
FROM Table1
INNER JOIN Table2
ON Table1.ProductName= Table2.ProductName
Try this:
SELECT ProductName,NumberofProducts ,NumberofProductssold
FROM table1
JOIN table2
ON table1.ProductName = table2.ProductName
Try this:
GET THE RECORD FOR CURRENT_MONTH, LAST_MONTH AND ALL_TIME AND MERGE THEM INTO SINGLE ARRAY
$analyticsData = $this->user->getMemberInfoCurrentMonth($userId);
$analyticsData1 = $this->user->getMemberInfoLastMonth($userId);
$analyticsData2 = $this->user->getMemberInfAllTime($userId);
foreach ($analyticsData2 as $arr) {
foreach ($analyticsData1 as $arr1) {
if ($arr->fullname == $arr1->fullname) {
$arr->last_send_count = $arr1->last_send_count;
break;
}else{
$arr->last_send_count = 0;
}
}
foreach ($analyticsData as $arr2) {
if ($arr->fullname == $arr2->fullname) {
$arr->current_send_count = $arr2->current_send_count;
break;
}else{
$arr->current_send_count = 0;
}
}
}
echo "<pre>";
print_r($analyticsData2);die;

MySQL count() problem

Setup:
create table main(id integer unsigned);
create table test1(id integer unsigned);
create table test2(id integer unsigned);
insert into main(id) value(1);
insert into test1(id) value(1);
insert into test1(id) value(1);
insert into test2(id) value(1);
insert into test2(id) value(1);
insert into test2(id) value(1);
Using:
select main.id,
count(test1.id),
count(test2.id)
from main
left join test1 on main.id=test1.id
left join test2 on main.id=test2.id
group by main.id;
...returns:
+------+-----------------+-----------------+
| id | count(test1.id) | count(test2.id) |
+------+-----------------+-----------------+
| 1 | 6 | 6 |
+------+-----------------+-----------------+
How to get the desired result of 1 2 3?
EDIT
The solution should be extensible,I'm going to query multiple count() information about main.id in the future.
Not optimal, but works:
select
count(*),
(select count(*) from test1 where test1.id = main.id) as test1_count,
(select count(*) from test2 where test2.id = main.id) as test2_count
from main
You created tables that contain the following:
Table main
id
----
1
Table test1
id
----
1
1
Table test2
id
----
1
1
1
When you join this like you do you will get the following
id id id
-----------
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
So how should SQL answer differently?
You can call:
SELECT id,COUNT(id) FROM main GROUP BY id
for every table, then join them by id.
Not sure if this works in MySQL exactly as written (I'm using Oracle):
1 select main.id, t1.rowcount, t2.rowcount
2 from main
3 left join (select id,count(*) rowcount from test1 group by id) t1
4 on t1.id = main.id
5 left join (select id,count(*) rowcount from test2 group by id) t2
6* on t2.id = main.id
SQL> /
ID ROWCOUNT ROWCOUNT
1 2 3
You're inadvertently creating a Cartesian product between test1 and test2, so every matching row in test1 is combined with every matching row in test2. The result of both counts, therefore, is the count of matching rows in test1 multiplied by the count of matching rows in test2.
This is a common SQL antipattern. A lot of people have this problem, because they think they have to get both counts in a single query.
Some other folks on this thread have suggested ways of compensating for the Cartesian product through creative use of subqueries, but the solution is simply to run two separate queries:
select main.id, count(test1.id)
from main
left join test1 on main.id=test1.id
group by main.id;
select main.id, count(test2.id)
from main
left join test2 on main.id=test2.id
group by main.id;
You don't have to do every task in a single SQL query! Frequently it's easier to code -- and easier for the RDBMS to execute -- multiple simpler queries.
You can get the desired result by using:
SELECT COUNT(*) as main_count,
(SELECT COUNT(*) FROM table1) as table1Count,
(SELECT COUNT(*) from table2) as table2Count FROM main