I have to make a SQL query wraping all of theses statements:
First, I have a first SQL query like this:
SELECT COUNT(*) as NbOfEntries from table1 where colName = "some condition"
Then, I have another SQL statement like this:
SELECT
t2.col1 as col1,
t2.col2 as col2,
t3.col3 as col3
FROM table2 t2
INNER JOIN table3 t3
ON t2.colName = t3.colName
WHERE t2.colName = "some condition"
Finally, based on the first SQL statement, I have to add a row of fake data on the result of the second statement if NbOfEntries > 0. I have to add an UNION to the second SQL query like this:
SELECT
"Dumb string 1" as col1,
"Dumb string 2" as col2,
"Dumb string 3" as col3
FROM DUAL -- or something like that, I don't know how it works
I thought about using UNION but, I don't know how to use UNION with a condition. In addition, I do not know how to generate fake data with SELECT in Oracle, I have already looked at how DUAL works but I have not really been able to move forward.
Thank you.
EDIT: Sample data
If the first statement returns 0, I have these rows:
col1 col2 col3
A AB 3
A AC 7
A AD 2
If the first statement returns > 0, I ihave to add one fake row to the result like this:
col1 col2 col3
A AB 3
A AC 7
A AD 2
X XX 0 // << Add this last row
You can use EXISTS like this:
SELECT
t2.col1 as col1,
t2.col2 as col2,
t3.col3 as col3
FROM table2 t2
INNER JOIN table3 t3
ON t2.colName = t3.colName
WHERE t2.colName = "some condition"
UNION ALL
SELECT
"Dumb string 1" as col1,
"Dumb string 2" as col2,
"Dumb string 3" as col3
FROM DUAL
WHERE EXISTS (
SELECT 1 from table1
where colName = "some condition"
)
There is no need to count the rows of table1.
EXISTS will return TRUE if there is 1 row that meets the condition.
You could jut use a HAVING clause for filtering:
SELECT t2.col1 as col1, t2.col2 as col2, t3.col3 as col3
FROM table2 t2
INNER JOIN table3 t3 ON t2.colName = t3.colName
WHERE t2.colName = 'some condition'
UNION ALL
SELECT 'X', 'XX', 0
FROM table1
WHERE colName = 'some condition'
HAVING COUNT(*) > 1
Related
I would like to understand the easy/better way to join 2 tables with same characteristics and different measures as an example described below:
tab1
Col1
Col2
Measure1
1
1
10
1
2
5
tab2
Col1
Col2
Measure2
1
1
20
2
1
25
Expected Result
Col1
Col2
Measure1
Measure2
1
1
10
20
1
2
5
0
2
1
0
25
Questions:
How to avoid message: Ambiguous column name col1?
How to create a correct Join?
I have tried:
select col1, col2, t1.Measure1, t2.Measure2
from tab1 t1
full outer jon tab2 t2
on t1.col1 = t2.col1
and t1.col2 = t2.col2
I have tried a Union and it works, but i am looking a easy way using joins:
Select col1, col2, Measure1, 0 as Measure2 From tab1
Union
Select col1, col2, 0 as Measure1, Measure2 From tab2
The full join is the correct approach. But you need to disambiguate col1 and col2 in the select clause: both tables have both columns, so it is unclear to which column an unprefixed col1 refers.
A typical approach uses coalesce():
select
coalesce(t1.col1, t2.col1) col1,
coalesce(t1.col2, t2.col2) col2,
coalesce(t1.measure1, 0) measure1,
coalesce(t2.measure2, 0) measure2
from tab1 t1
full outer jon tab2 t2
on t1.col1 = t2.col1 and t1.col2 = t2.col2
Note that you also need coalesce() around the measures to return 0 instead of null on "missing" values.
In some databases (eg Postgres), you can use the using syntax to declare the join conditions for columns that have the same name across the tables ; this syntax automagically disambiguates the unprefixed column names, so:
select
col1,
col2,
coalesce(t1.measure1, 0) measure1,
coalesce(t2.measure2, 0) measure2
from tab1 t1
full join tab2 t2 using (col1, col2)
You should reference source tables for col1 and col2 as well.
As you're using FULL OUTER JOIN I'd recommend using COALESCE statement.
SELECT COALESCE(t1.col1, t2.col1) as col1,
COALESCE(t1.col2, t2.col2) as col2,
t1.Measure1,
t2.Measure2
FROM tab1 t1
FULL OUTER JOIN tab2 t2
on t1.col1 = t2.col1
and t1.col2 = t2.col2
A sample table with two column and I need to compare the column 1 and column 2 to the same table records and need to remove the column 1 + column 2 = column 2+column 1.
I tried to do self join and case condition. But its not working
If I understand correctly, you can run a simple select like this if you have all reversed pairs in the table:
select col1, col2
from t
where col1 < col2;
If you have some singletons, then:
select col1, col2
from t
where col1 < col2 or
(col1 > col2 and
not exists (select 1
from t t2
where t2.col1 = t.col2 and
t2.col2 = t.col1
)
);
You can use the except operator.
"EXCEPT returns distinct rows from the left input query that aren't output by the right input query."
SELECT C1, C2 FROM table
Except
SELECT C2, C1 FROM table
Example with your given data set : dbfiddle
I am posting the answer based on oracle database and also the columns are string/varchar:
delete from table where rowid in (
select rowid from table
where column1 || column2 =column2 || column1 )
Feel free to provide more input and we can tweak the answer.
Okay. There might be a simpler way of doing this but this might work as well. {table} is to be replaced with your table name.
;with orderedtable as (select t1.col1, t1.col2, ROW_NUMBER() OVER(ORDER BY t1.col1, t1.col2 ASC) AS rownum
from (select distinct t2.col1, t2.col2 from {table} t2) as t1)
select f1.col1, f1.col2
from orderedtable f1
left join orderedtable f2 on f1.col1 = f2.col2 and f1.col2 = f2.col1 and f1.rownum < f2.rownum
where f2.rownum is null
The SQL below will get the reversed col1 and col2 rows:
select
distinct t2.col1,t1.col2
from
table t1
join
table t2 on t1.col1 = t2.col2 and t1.col2 = t2.col1
And when we get these reversed rows, we can except them with the left join clause, the complete SQL is:
select
t.col1,t.col2
from
table t
left join
(
select
distinct t2.col1,t1.col2
from
table t1
join
table t2 on t1.col1 = t2.col2 and t1.col2 = t2.col1
) tmp on t.col1 = tmp.col1 and t.col2 = tmp.col2
where
tmp.col1 is null
Is it clear?
We have a SQL query which is not written as per the sql guideline. We have to change the query but if we change the logic and remove the inner query then it take to much time to execute. Below is the query:
select col1,
col2,
case
when col1 <> '' then(select top 1
col1
from table1 as BP
where bp.col1 = FD.col1 order by BP.col1)
when col2 <> '' then(select top 1
BP.col2
from table1 as BP
where BP.col2 = FD.col2 order by BP.col2)
else ''
end
from table2 FD
The above query is being used to insert the data into a temp table. The table1 has almost 100 million of data. Is there any way to remove the inline query along with the good performance. We have already created the indexes on table1. Any thought?
Try this
;WITH CTE
AS
(
SELECT
RN = ROW_NUMBER() OVER(ORDER BY COALESCE(T2.col1,T2.col2)),
T2.col1,
T2.col2,
T1Val = COALESCE(T2.col1,T2.col2,'')
FROM table2 T2
LEFT JOIN table1 T1
ON
(
(
ISNULL(T2.col1,'')<>'' AND T1.col1 = T2.col1
)
OR
(
ISNULL(T2.col2,'')<>'' AND T1.col2 = T2.col2
)
)
)
SELECT
*
FROM CTE
WHERE RN = 1
Here is my modest help:
You can already prepare and materialize your subquery1 and subquery2 (Group BY col1 or col2) <-- It will reduce the size of your table 1)
Split your main query (from table2 into 3 different queries)
1 with SELECT .. FROM table2 WHERE col1 <> ''
1 with SELECT .. FROM table2 WHERE col1 = '' AND col2 <> ''
1 with SELECT .. FROM table2 WHERE col1 = '' AND col2 = ''
Use an INNER JOIN with your table created in the first point.
(If you use SSIS you can // and use your inner join table into a Lookup)
If your col1 or col2 use a NVARCHAR(MAX) or a big size, you should have a look to a HashFunction (MD5 for example) and compare Hash instead.
Be sure to have all your indexes
At least if it is not performant, you can try with:
OUTER APPLY (SELECT TOP 1 .. )
Another idea should be:
SELECT col1, col2, col1 AS yourNewCol
FROM table2 T2
WHERE EXISTS( SELECT 1 FROM table1 T1 WHERE T1.col1 = T2.col1)
UNION ALL
SELECT col1, col2, col2 AS yourNewCol
FROM table2 T2
WHERE
NOT EXISTS( SELECT 1 FROM table1 T1 WHERE T1.col1 = T2.col1)
AND EXISTS( SELECT 1 FROM table1 T1 WHERE T1.col2 = T2.col2)
UNION ALL
...
I don't have a clean solution for you, but some ideas.
Let me know if it helps you.
Regards,
Arnaud
The have the following 2 table2:
Table1(col1 integer, col2)
1 "This is a string"
2 "This is another string"
5 "This is yet another string"
3 "a"
4 "b"
6 "Some other string"
Table2(col3 integer, col4 integer, col5 integer)
1 2 5
3 4 6
Now I want to find all the values from Table2 where col4=2. This gives me col3=1 and col5=5. Now I want to join this result with Table1 such that I obtain the string values(col2) corresponding to these integers.
That is, I want the result as: "This is a string", "This is yet another string"
The SQL query which I wrote in postgresql is given below:
select d1.col2, d2.col2
from Table1 d1, Table1 d2
where (select col3, col5 from Table2 where col4=0);
However, the above query is giving me error. Can someone please help me write an efficient query for the same.
You could use an INNER JOIN with two conditions on the ON clause:
SELECT Table1.*
FROM
Table1 INNER JOIN Table2
ON Table1.col1 = Table2.col3 OR Table1.col1 = Table2.col5
WHERE
Table2.col4=2
Please see fiddle here.
Try
SELECT t2.col2, t3.col2
FROM Table1 AS t1
INNER JOIN Table2 AS t2 ON t1.col1 = t2.col3
INNER JOIN Table2 AS t3 ON t1.col1 = t2.col5
WHERE t1.col4 = 2
if you want your result as two rows with one column:
select t1.col2
from Table2 as t2
inner join Table1 as t1 on t1.col1 in (t2.col3, t2.col5)
where t2.col4 = 2;
-- output
-- 'This is a string'
-- 'This is yet another string'
if you want your result as one row with two columns:
select t13.col2, t15.col2
from Table2 as t2
inner join Table1 as t13 on t13.col1 = t2.col3
inner join Table1 as t15 on t15.col1 = t2.col5
where t2.col4 = 2
-- output
-- 'This is a string', 'This is yet another string'
sql fiddle demo
try it as a union
select col2 from table1 where col1 in (
select col3 from table2 where col4 = 2
union
select col5 from table2 where col4 = 2
)
I was wondering if there exists code to accomplish the following in SQL-Server 2008?
Table 1:
id column name
-------------------
1 col1
2 col2
3 col3
4 col2
Table 2:
col1 col2 col3
--------------------
a b c
Result Table:
id data
--------------------
1 a
2 b
3 c
4 b
Thanks in advance, I really have no idea how to do this.
You can use UNPIVOT table2 to access the data from the columns:
select t1.id, t2.value
from table1 t1
left join
(
select value, col
from table2
unpivot
(
value
for col in (col1, col2, col3)
) u
) t2
on t1.name = t2.col
see SQL Fiddle with Demo
Or you can use a UNION ALL to access the data in table2:
select t1.id, t2.value
from table1 t1
left join
(
select col1 value, 'col1' col
from table2
union all
select col2 value, 'col2' col
from table2
union all
select col3 value, 'col3' col
from table2
) t2
on t1.name = t2.col
see SQL Fiddle with Demo
I dont see how you do it withou a column connection them:
Table1:
ID
ColumnName
Table2:
Table1ID
Letter
Select table1.id, table2.Letter
from table1
inner join table2 on table1.ID = table2.Table1ID
You can do this with a case statement and cross join:
select t1.id,
(case when t1.columnname = 'col1' then t2.col1
when t1.columnname = 'col2' then t2.col2
when t1.columnname = 'col3' then t2.col3
end) as data
from table1 t1 cross join
table2 t2