grouping IN statement sql - sql

lets say I have a table called table1 and it's corresponding columns are col1, col2, col3 and col4 for example.
what will be the equivalent thing of doing:
-- note that the following query will not work
SELECT *
FROM table1
WHERE col1, col2 IN (SELECT col1, col2
FROM table1
WHERE col3 < 4)
Do I have to merge col1 and col2 in my database to make this work? If I merge col1 and col2 into col1_2 then I will be able to make the above query work by writing:
SELECT *
FROM table1
WHERE col1_2 IN (SELECT col1_2
FROM table1
WHERE col3 < 4)
The IN clause works fine when using one column. it will be nice if I could use it with several columns without having to modify the database.

SELECT * from table1 t1, table1 t2
where t1.col1=t2.col1 and t1.COl2=t2.Col2 and t1.col3<4
try this one

Equivalent of what you showed is:
SELECT *
FROM table1 tb1
WHERE EXISTS
(
SELECT *
FROM table1 tb2
WHERE
tb1.col1 = tb2.col1 and
tb1.col2 = tb2.col2 and
tb2.col3 < 4
)
However, this query does not make much sense as it is equivalent of
SELECT *
FROM table1 tb1
WHERE tb2.col3 < 4
I just assume that the example you show is not well thought out.

Related

Remove duplicate rows from one column

The problem is:
select (..)
UNION
select (..)
Result is:
Col1, Col2, Col3
Val1 Text1 Data
Val1 Text2 Data
The problem is that i need to save only 1 row of this two. Col2 value is not same at fact, but the same in business logic.
So, how to get result like this:
Col1, Col2,Col3
Val1 Text1 Data
OR
Col1, Col2, Col3
Val1 Text2 Data
Thank you!
You can place the UNION in a subquery and group again
SELECT
Col1,
MIN(Col2),
Col3
FROM (
SELECT Col1, Col2, Col3
FROM table1 t1
UNION ALL
SELECT Col1, Col2, Col3
FROM table2 t2
) t
GROUP BY
Col1,
Col2;
Note the use of UNION ALL rather than UNION, because you are grouping anyway it is not necessary to de-duplicate first.
Hmmm . . . If you want one row per val, then one method is:
with t1 as ( < query 1 here > ),
t2 as ( < query 2 here > )
select t1.*
from t1
union all
select t2.*
from t2
where not exists (select 1 from t1 where t1.val = t2.val);

sql creating result set of different mismatches of two tables based on different groups as shown in image

How to find difference of two tables based on different group: I have a below scenario:
(TABLE1
COL1=1,2,3,4,5
Table2
COL1=1,2,3,4,5
COL2=A,B,C.....
COL3=XXX OR BLANK
output
1A,1B,1C,2A,2B
)
I got the below sql but my column2 has 40 different value and it will be a big union all statement. Also the comparison needs to be done with all entries of table 1 needs to compare with table2 as A has (1,2,3 in table1 ) B has (2,3 in table2) any way to achieve it efficiently will be highly appreciated ?
Edit:
Col2 value should not be hardcoded it should be distinct value from Table2, it can be from a-z, so my below union all will have 26 statement having same code just col2 will changeenter image description here
/*SQL that is working result: */
SELECT col1
FROM table1
WHERE col1 NOT IN (
SELECT col1
FROM table2
WHERE col3 = 'xxx'
AND col2 = 'A'
)
UNION ALL
SELECT col1
FROM table1
WHERE col1 NOT IN (
SELECT col1
FROM table2
WHERE col3 = 'xxx'
AND col2 = 'B'
)
UNION ALL
SELECT col1
FROM table1
WHERE col1 NOT IN (
SELECT col1
FROM table2
WHERE col3 = 'xxx'
AND col2 = 'C'
)
Are you looking for logic like this? For your example all the col3s are the same, so:
SELECT t1.col1
FROM table1 t1
WHERE NOT EXISTS (SELECT 1
FROM table2 t2
WHERE t2.col1 = t1.col1 AND
t2.col3 = 'xxx' AND
t2.col1 IN ('A', 'B', 'C')
);
This assumes that the comparison on col3 is always 'xxx' as in your example. The logic can easily be tweaked if that is not the case.

SQL - Delete repeated rows in table

I need to delete the repeated row-
I have this table-
source
The result that I need-
result
*keep only one combination of 2 column (the order is not important)
Thanks! (:
Here is one method that should be efficient:
select col1, col2
from t
where col1 <= col2
union all
select col1, col2
from t
where col1 > col2 and
not exists (select 1 from t t2 where t2.col1 = t.col2 and t2.col2 = t.col1);
Note: This is a SQL select statement, so it does not delete rows in the table. You seem to want the results from a query, not to modify the underlying table.
My interpretation of the spec "keep only one combination of 2 column, [column] order not important":
SELECT col1, col2
FROM t
WHERE col1 <= col2
UNION
SELECT col2, col1
FROM t
WHERE col1 > col2;

merge two queries with different where and different grouping into 1

Sorry, I asked this question just before and got some good answers but then I realised I made a mistake with the query in question, if I change the question in the original post that could make the answers invalid so I'm posting again with the right query this time, please forgive me, I hope this is acceptable.
DECLARE #Temp TABLE
(MeasureDate, col1, col2, type)
INSERT INTO #Temp
SELECT MeasureDate, col1, col2, 1
FROM Table1
WHERE Col3 = 1
INSERT INTO #Temp
SELECT MeasureDate, col1, col2, 3
FROM Table1
WHERE Col3 = 1
AND Col4 = 7000
SELECT SUM(col1) / SUM(col2) AS Percentage, MeasureDate, Type
FROM #Temp
GROUP BY MeasureDate, Type
I do two inserts into the temp table, 2nd insert with an extra WHERE but same columns same table, but different type, then I do SUM(col1) / SUM(col2) on the temp table to return the result I need per MeasureDate and type. Is there a way to merge all these inserts and selects into one statement so I don't use a temp table and do a single select from Table1? Or even if I still need the temp table, merge the selects into one select instead of two separate selects? Stored procedure works fine as it is, just looking for a way to shorten it.
Thanks.
Sure can. I might start with combining the two queries from your inserts using UNION ALL (this variation of UNION will not remove duplicates), wrapped up in a CTE from which you can perform your final query:
WITH MeasureData(MeasureDate, col1, col2, type) AS (
SELECT MeasureDate, col1, col2, 1
FROM Table1
WHERE Col3 = 1
UNION ALL
SELECT MeasureDate, col1, col2, 3
FROM Table1
WHERE Col3 = 1
AND Col4 = 7000
)
SELECT SUM(col1) / SUM(col2) AS Percentage, MeasureDate, Type
FROM MeasureData
GROUP BY MeasureDate, Type
That's it, no more table variable or insert statements.
No real need for a UNION, you can handle this with a CASE statement:
SELECT SUM(col1) / SUM(col2) AS Percentage, MeasureDate, Type
FROM (
SELECT MeasureDate, col1, col2, case when Col4 = 7000 then 3 else 1 end type
FROM Table1
WHERE Col3 = 1
) t
GROUP BY MeasureDate, Type
Edit, as Gordon correctly points out, for Type = 1, this query wouldn't produce the same results. Here's a variation on Gordon's good answer that might be easier to visually understand using a CROSS JOIN and IF logic:
SELECT T1.MeasureDate,
T.Type,
SUM(IF(T.Type=1,Col1,IF(T.Type=3 AND T1.Col4=7000,T1.Col1,0))) /
SUM(IF(T.Type=1,Col2,IF(T.Type=3 AND T1.Col4=7000,T1.Col2,0))) AS Percentage
FROM Table1 T1
CROSS JOIN (SELECT 1 Type UNION SELECT 3) T
WHERE T1.Col3 = 1
GROUP BY T1.MeasureDate, T.Type
Condensed SQL Fiddle
Your method is double counting cases where col3 = 1 and col4 = 7000. Here is a method that takes this into account, without union on the overall table:
select t.type, SUM(t1.col1) / SUM(t1.col2) AS Percentage, t1.MeasureDate, t.Type
from table1 t1 join
(select 1 as type union all
select 3 as type
) t
on t.type = 1 or t1.col4 = 7000
where t1.col3 = 1
group by measuredate, type;

Select only when first select is null

I really dont get this, tried with coalesce() but with no result...
I have one select (very simplified to understand the problem):
select col1,
col2
from table1 t1
where table1.col1='value'
and table1.col2='value2'
and table1.col3='value3'
And i really need a result so if this select resultset is null (and only if it is null) (no result) then the following sql select came to picture
select col1,
col2
from table1 t1
where table1.col1='another_value'
and table1.col2='another_value2'
How can i get this two in to one big select? (any syntax which is recommended is appreciated...)
Something like:
; WITH Base AS (
select col1,
col2
from table1 t1
where table1.col1='value'
and table1.col2='value2'
and table1.col3='value3'
)
, Base2 AS (
select col1,
col2
from table1 t1
where table1.col1='another_value'
and table1.col2='another_value2'
AND NOT EXISTS (SELECT 1 FROM Base) -- HERE!!!
)
SELECT * FROM Base
UNION
SELECT * FROM Base2
and let's hope the SQL optimizer won't run the first query twice :-)
It is a CTE (Common Table Expression)... I used it so I could reuse the first query twice (one in the EXISTS and the other in the SELECT ... UNION)
By using a temporary table
select col1,
col2
INTO #temp1 -- HERE!!!
from table1 t1
where table1.col1='value'
and table1.col2='value2'
and table1.col3='value3'
select col1,
col2
from table1 t1
where table1.col1='another_value'
and table1.col2='another_value2'
AND NOT EXISTS (SELECT 1 FROM #temp1) -- HERE!!!
It could benefit us a little better if you had a little more information in your example. Is there a common value between the two tables that a JOIN can be established?
SELECT col1
,col2
FROM Table1 t1
WHERE table1.col1='value'
and table1.col2='value2'
and table1.col3='value3'
UNION
SELECT col1
,col2
FROM Table2 t2
WHERE table1.col1='another_value'
and table1.col2='another_value2'
WHERE NOT EXISTS (SELECT 1 FROM Table1 t1 WHERE t1.Col1 = t2.Col2)
You can use COALESCE, like this:
select COALESCE (
(select col1,
col2
from table1 t1
where table1.col1='value'
and table1.col2='value2'
and table1.col3='value3')
,
(select col1,
col2
from table1 t1
where table1.col1='another_value'
and table1.col2='another_value2')
)
Here are my ugly solution.
select top 1 with ties
col1,
col2
from table1
where (
col1='value'
and col2='value2'
and col3='value3'
) OR
(
col1='another_value'
and col2='another_value2'
)
order by
CASE
WHEN col1='value'
and col2='value2'
and col3='value3'
THEN 1
WHEN col1='another_value'
and col2='another_value2'
THEN 2 END
SQL Fiddle DEMO