SQL get records from table where results from another table is in the range defined by Col1 and Col2? - sql

I have the following ranges from a query:
Col1 Col2
--------------
100-200
200-300
300-400
and this vector from another query:
Nbr
----
119
351
149
I want to get the ranges for the numbers on the vector.
Is there a way to do this in SQL without recurring to iterations? Something like:
SELECT Col1, Col2
FROM TB1
WHERE (SELECT Nbr FROM TB2) BETWEEN Col1 and Col2
The above query doesn't work because multiple results are returned.
Thank you.

Yes. Just use a join:
SELECT TB1.Col1, TB1.Col2
FROM TB1 JOIN
TB2
ON TB2.Nbr BETWEEN TB1.Col1 and TB1.Col2;

Related

Count to begin at 1

I want to value a column with a count. I am looking through the table to find the next count number. If a row does not exists I would like to begin the count with 1 rather than 0. Can someone assist me with my below query. If a row does exist then I would like to simply take the column 3 and add 1 to the next sequence number.
SELECT
COl1,
Col2,
CAST((MAX(col3) + 1) AS SMALLINT) AS col3
FROM table1
GROUP BY col1, col2
You are using a MAX() function that returns the highest value. If you want to count the number of occurences (rows), you need to use the COUNT() function.
Edit
More details would be needed, but in SQL Server you could try something like this:
SELECT col1, col2, count(1) + 1 as col3
FROM table1
GROUP BY col1, col2
It would count the number of distinct pair of col1 and col2, then add one to it and display it as col3. From what I understand, you do not really need to use the current value of col3, since you are recalculating it.
If you want all combinaison with 1 if one combinaison dont exist try this:
with combinaison as (
select distinct f1.col1, f2.col2
from table1 f1 cross join table1 f2
)
SELECT f1.col1, f1.col2, ifnull(MAX(f1.col3), 0) + 1 AS col3
FROM table1 f1
GROUP BY f1.col1, f1.col2
union all
select f2.col1, f2.col2, 1 AS col3
from combinaison f2 left outer join table1 f3 on (f2.col1, f2.col2)=(f3.col1, f3.col2)
where f3.col1 is null

Exclude rows that have same value in two different columns

I have a table which has 2 columns that sometimes have the same values. I want to know how to exclude the rows where the value of column1 is equal to a value in column2.
EXAMPLE:
COL1 | COL2
1 -------- 7
2 -------- 8
3 -------- 2
4 -------- 5
5 -------- 9
Here I would exclude rows 2 and 5.
Thanks
select
*
from table
where col1 not in (
select
column2
from table
)
Something like this should work :
SELECT *
FROM yourtable
WHERE COL1 NOT IN (SELECT COL2
FROM yourtable)
I tend to avoid using IN for long lists of values, as it performs poorly on some database systems. The following selects all values from col1 that are not present in col2:
SELECT col1
FROM
yourtable t1
LEFT JOIN
yourtable t2
ON
t1.col1 = t2.col2
WHERE
t2.col2 IS NULL
Why does it work? Well, normally the join operator will link together rows that have the same value. Left join will keep some rows that are mismatched though (and it's those we want). The left join takes the table on the left (t1) and uses it as the reference table, and starts associating rows from the table on the right (after the word JOIN, in this case t2). If the col1 value has a matching value in col2 then the row will be fully populated with values for each. If the value from col1 has no matching value from col2, the col2 cell on the resulting row is blank/null. Because we hence want to know only those values that aren't matched, we say "where col2 is null"
The other trick with getting to grips with this is in understanding that the same table can appear twice in a query. We give it a different alias each time we use it so we can tell them apart. You could conceive it as virtually making a copy of the table, before it links them together
Use EXCEPT together with a correlated sub-query - as shown below.
Read up on EXCEPT here: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/set-operators-except-and-intersect-transact-sql
SELECT *
FROM TEST
EXCEPT
SELECT *
FROM TEST
WHERE COL1 IN (
SELECT COL2
FROM TEST
)
not sure, but maybe...
SELECT t1.*
FROM my_table AS t1
LEFT JOIN my_table AS t2
ON t2.col_b = t1.col_a
WHERE t2.col_b IS NULL

Oracle SQL How to find duplicate values in different columns?

I have a set of rows with many columns. For example,
ID | Col1 | Col2 | Col3 | Duplicate
------------------------------------
81 | 101 | 102 | 101 | YES
82 | 101 | 103 | 104 | NO
I need to calculate the "Duplicate" column. It is duplicate because it has the same value in Col1 and Col3. I know there is the LEAST function, which is similar to the MIN function but with columns. Does something similar to achieve this exists?
The approach I have in mind is to write all possible combinations in a case like this:
SELECT ID, col1, col2, col3,
CASE WHEN col1 = col2 or col1 = col3 or col2 = col3 then 1 else 0 end as Duplicate
FROM table
But, I wish to avoid that, since I have too many columns in some cases, and is very prone to errors.
What is the best way to solve this?
Hmmm. You are looking for within-row duplicates. This is painful. More recent versions of Oracle support lateral joins. But for just a handful of non-NULL columns, you can do:
select id, col1, col2, col3,
(case when col1 in (col2, col3) or col2 in (col3) then 1 else 0 end) as Duplicate
from t;
For each additional column, you need to add one more in comparison and update the other in-lists.
Something like this... note that in the lateral clause we still need to unpivot, but that is one row at a time - resulting in possibly much faster execution than simple unpivot and standard aggregation.
with
input_data ( id, col1, col2, col3 ) as (
select 81, 101, 102, 101 from dual union all
select 82, 101, 103, 104 from dual
)
-- End of simulated input data (for testing purposes only).
-- Solution (SQL query) begins BELOW THIS LINE.
select i.id, i.col1, i.col2, i.col3, l.duplicates
from input_data i,
lateral ( select case when count (distinct val) = count(val)
then 'NO' else 'YES'
end as duplicates
from input_data
unpivot ( val for col in ( col1, col2, col3 ) )
where id = i.id
) l
;
ID COL1 COL2 COL3 DUPLICATES
-- ---- ---- ---- ----------
81 101 102 101 YES
82 101 103 104 NO
You can do this by unpivoting and then counting the distinct values per id and checking if it equals the number of rows for that id. Equal means there are no duplicates. Then left join this result to the original table to caclulate the duplicate column.
SELECT t.*,
CASE WHEN x.id IS NOT NULL THEN 'Yes' ELSE 'No' END AS duplicate
FROM t
LEFT JOIN
(SELECT id
FROM
(SELECT *
FROM t
unpivot (val FOR col IN (col1,col2,col3)) u
) t
GROUP BY id
HAVING count(*)<>count(DISTINCT val)
) x ON x.id=t.id
The best way† is to avoid storing repeating groups of columns. If you have multiple columns that essentially store comparable data (i.e. a multi-valued attribute), move the data to a dependent table, and use one column.
CREATE TABLE child (
ref_id INT,
col INT
);
INSERT INTO child VALUES
(81, 101), (81, 102), (81, 101),
(82, 101), (82, 103), (82, 104);
Then it's easier to find cases where a value occurs more than once:
SELECT id, col, COUNT(*)
FROM child
GROUP BY id, col
HAVING COUNT(*) > 1;
If you can't change the structure of the table, you could simulate it using UNIONs:
SELECT id, col1, COUNT(*)
FROM (
SELECT id, col1 AS col FROM mytable
UNION ALL SELECT id, col2 FROM mytable
UNION ALL SELECT id, col3 FROM mytable
... for more columns ...
) t
GROUP BY id, col
HAVING COUNT(*) > 1;
† Best for the query you are trying to run. A denormalized storage strategy might be better for some other types of queries.
SELECT ID, col1, col2,
NVL2(NULLIF(col1, col2), 'Not duplicate', 'Duplicate')
FROM table;
If you want to compare more than 2 columns can implement same logic with COALESCE
I think you want to use fresh data that doesnot contains any duplicate values inside table if it right then use SELECT DISTINCT statement like
SELECT DISTINCT * FROM TABLE_NAME
It will conatins duplicate free data,
Note: It will also applicable for a particular column like
SELECT DISTINCT col1 FROM TABLE_NAME

Two equal tables (different column numbers) have different number of rows

AWS Redshift DB
I have two tables A and B
select col1, col2 from A
except
select col1, col2 from B
returns empty, the same
select col1, col2 from B
except
select col1, col2 from A
returns empty
but
select count(*) from A
returns for example 100, but
select count(*) from B
returns 200
how can that be ?
Because each tables distinct data set is contained in the other. A different count means that you have duplicate rows. This might make it clearer.
Distinct(A) is a subset of B
Distinct(B) is a subset of A

Get row where column2 is X and column1 is max of column1

I have a SQLite table like this:
Col1 Col2 Col3
1 ABC Bill
2 CDE Fred
3 FGH Jack
4 CDE June
I would like to find the row containing a Col2 value of CDE which has the max Col1 value i.e. in this case June. Or, put another way, the most recently added row with a col2 value of CDE, as Col1 is an auto increment column. What is an SQL query string to achieve this? I need this to be efficient as the query will run many iterations in a loop.
Thanks.
SELECT * FROM table WHERE col2='CDE' ORDER BY col1 DESC LIMIT 1
in case if col1 wasn't an increment it would go somewhat like
SELECT *,MAX(col1) AS max_col1 FROM table WHERE col2='CDE' GROUP BY col2 LIMIT 1
Try this:
SELECT t1.*
FROM table1 t1
INNER JOIN
(
SELECT MAX(col1) MAXID, col2
FROM table1
GROUP BY col2
) t2 ON t1.col1 = t2.maxID AND t1.col2 = t2.col2
WHERE t1.col2 = 'CDE';
SQL Fiddle Demo1
1: This demo is mysql, but it should work fine with the same syntax in sqlite.
Use a subquery such as:
SELECT Col1, Col2, Col3
FROM table
WHERE Col1 = (SELECT MAX(Col1) FROM table WHERE Col2='CDE')
Add indexes as appropriate, e.g. clustered index on Col1 and another nonclustered index on Col2 to speed up the subquery.
In SQLite 3.7.11 and later, the simplest query would be:
SELECT *, max(Col1) FROM MyTable WHERE Col2 = 'CDE'
As shown by EXPLAIN QUERY PLAN, both this and passingby's query are most efficient, if there is an index on Col2.
If you'd want to see the correspondig values for all Col2 values, use a query like this instead:
SELECT *, max(Col1) FROM MyTable GROUP BY Col2