Do you have ideas how could I isolate result from the following task..
I have a column which contrains the following value:
col_1
10001A
10001A10002A
10001A10002A10003A
10004A
10004A10005B
10006A
10007A
10007A10008A
I should select only the rows which don't have offsprings -
col_1
10001A10002A10003A
10004A10005B
10006A
10007A10008A
You need a like condition to find those rows:
select *
from the_table t1
where not exists (select *
from the_table t2
where t2.col_1 like t1.col_1||'%'
and t1.col_1 <> t2.col_2);
Online example: https://rextester.com/GVGVV77242
Related
Id like to find records with (.XX) extension at the end which don't have corresponding records without an extension (.XX) at the end. Id like to use the "exists" or "not exists" solution if possible as I'm puzzled why mine gives no output.
input
col_a
value1.XX
value1
value2.XX
value3
** expected output**
col_a
value2.XX
code
SELECT *
FROM table1 as a
where
right (table1.[col_a],3) = ".XX"
and exists(
select 1 from table1 b where Left(a.[col_a], Len(a.[col_a]) - 3) = b.[col_a]
)
Hmmm. You
select t1.*
from table1 t1
where t1.col_a like '%.XX' and
not exists (select 1
from table1 tt1
where t1.col_a = tt1.col_a || '.XX'
);
Note: You have not specified your database so this uses the ISO/ANSI standard || for string concatenation. You can check your RDBMs's documentation for the correct concatenation technique.
Following are the two tables in SQL Server: TABLE_A and TABLE_B
I need to get the output as follows:
Get IDs from TABLE_A where Exist = 0
We would get 100, 101 & 102
Now, among 100, 101 & 102, no other rows (in the same table) with the same ID value should have Exist = 1
Hence, 100 can't be selected as it has Exist = 1 in the 2nd row.
So, only 101 & 102 remain
With the remaining ID values (101 & 102), check against the ID column in TABLE_B where 'Exist' column value should not be equal to '1' in any of the rows
In TABLE_B, 4th row has Exist = 1 for 102. So, that can't be selected
We have only 101 now. This is required output and that should be selected.
Could you let me know how to write the simplest query to achieve this please? Let me know if the question needs to be improved.
You can use exists & not exists :
with t as (
select t1.*
from t1
where exists (select 1 from t1 t11 where t11.id = t1.id and t11.exists = 0) and
not exists (select 1 from t1 t11 where t11.id = t1.id and t11.exists = 1)
)
select t.*
from t
where not exists (select 1 from t2 where t.id = t2.id and t2.exists = 1);
Try:
SELECT
ID,
SUM(CAST(Exist AS int)) AS [Exists]
FROM
TABLE_A
GROUP BY ID
HAVING SUM(CAST(Exist AS bit)) = 0
will give you the answer to the first part. You can then JOIN this to a similar query for TABLE_B. That is a "simple" way to show how this works. You can write more complex queries as that from #Yogest Sharma
Like #Peter Smith mentioned, you can use the aggregate function SUM. Note that you would need a cast since you cannot use the aggregate function on a field that has a BIT datatype
;WITH CTE AS
(
SELECT ID, SUM(CAST(Exist AS INT)) AS AggExist FROM TABLE_A GROUP BY ID
UNION
SELECT ID, SUM(CAST(Exist AS INT)) As AggExist FROM TABLE_B GROUP BY ID
)
SELECT ID, SUM(AggExist) FROM CTE GROUP BY ID
HAVING SUM(AggExist) = 0
Here is the demo
I have 2 rows from 2 tables in a database that I want to compare.
Column1 is on table1 and is an Integer field with entries like the following
column1
147518
187146
169592
Column2 is on table2 and is a Varchar(15) field with various entries but for this example lets use these 3:
column2
169592
00010000089
DummyId
For my query part of it relies on checking if rows from table1 are linked to the rows in table2, but to do this, I need to compare column1 and column2.
SELECT * FROM table1 WHERE column1 IN (SELECT column2 FROM table2)
The result of this using the data above should be 1 row - 169592
Obviously this wont work (A character to numeric conversion process failed) as they cannot be compared as is, but how do I get them to work?
I have tried
SELECT * FROM table1 WHERE column1 IN (SELECT CAST(column2 AS INTEGER) FROM table2)
and
SELECT * FROM table1 WHERE column1 IN (SELECT (column2::INTEGER) column2 FROM table2)
Using Server Studio 9.1 if that helps.
Try casting the int to a string:
SELECT * FROM table1 WHERE cast(column1 as varchar(15)) IN (SELECT column2 FROM table2)
You can try to use ISNUMERIC in following:
SELECT * FROM table1 WHERE column1 IN (SELECT CASE WHEN ISNUMERIC(column2) = 1 THEN CAST(column2 AS INT) END FROM table2)
For this purpose there is no need to create a special function that you'll not find on other environments.
Let's create a test case for your example:
CREATE TABLE tab1 (
col1 INT,
col2 INT
);
CREATE TABLE tab2 (
col1 VARCHAR(15)
);
INSERT INTO tab1 VALUES(147518,1);
INSERT INTO tab1 VALUES(187146,2);
INSERT INTO tab1 VALUES(169592,3);
INSERT INTO tab2 VALUES(169592);
INSERT INTO tab2 VALUES('00010000089');
INSERT INTO tab2 VALUES('DummyId');
The first query you run was like:
SELECT t1.*
FROM tab1 AS t1
WHERE t1.col1 IN (SELECT t2.col1 FROM tab2 AS t2);
This will raise an error because it tries to compare an INT with a VARCHAR
[infx1210#tardis ~]$ finderr 1213
-1213 A character to numeric conversion process failed.
A character value is being converted to numeric form for storage in a
numeric column or variable. However, the character string cannot be
interpreted as a number. It contains some characters other than white
space, digits, a sign, a decimal, or the letter e; or the parts are in
the wrong order, so the number cannot be deciphered.
If you are using NLS, the decimal character or thousands separator
might be wrong for your locale.
[infx1210#tardis ~]$
Then you've tried to cast a VARCHAR into a INT which resulted in the same error, you should tried the other way:
> SELECT t1.*
> FROM tab1 AS t1
> WHERE t1.col1::CHAR(11) IN (SELECT t2.col1 FROM tab2 AS t2);
>
col1 col2
169592 3
1 row(s) retrieved.
>
Check also if you don't get faster results using the EXISTS:
> SELECT t1.*
> FROM tab1 AS t1
> WHERE EXISTS (
> SELECT 1
> FROM tab2 AS t2
> WHERE t1.col1::CHAR(11) = t2.col1
> );
col1 col2
169592 3
1 row(s) retrieved.
>
Another way possible is to just join the tables:
> SELECT t1.*
> FROM tab1 AS t1
> INNER JOIN tab2 AS t2
> ON (t1.col1 = t2.col1);
col1 col2
169592 3
1 row(s) retrieved.
>
Part of this question was answered by #Stanislovas Kalašnikovas where he said to use the following:
SELECT * FROM table1 WHERE column1 IN (SELECT CASE WHEN ISNUMERIC(column2) = 1 THEN CAST(column2 AS INT) END FROM table2)
But informix does not have a built in function for ISNUMERIC, so the following created it:
create function isnumeric2(inputstr varchar(15)) returning integer;
define numeric_var decimal(15,0);
define function_rtn integer;
on exception in (-1213)
let function_rtn = 0;
end exception with resume
let function_rtn = 1;
let numeric_var = inputstr;
return function_rtn;
end function;
And then the first query above worked for me.
Suppose I have a SQL Server table with many columns something along the lines of:
Col1: Col2: Col3: ... Coln:
Val1_1 Val1_2 Val1_3 Val1_n
Val2_1 Val2_2 Val2_3 Val2_n
Val3_1 Val3_2 Val3_3 Val3_n
Val3_1 Val4_2 Val4_3 Val4_n
Val3_1 Val5_2 Val5_3 Val5_n
In this case, Val3_1 is repeated in Col1 for the last 3 records, whereas the remaining values are not repeated.
How can I write a query to return the full set of columns where Col1's value is duplicated to get back:
Col1: Col2: Col3: ... Coln:
Val3_1 Val3_2 Val3_3 Val3_n
Val3_1 Val4_2 Val4_3 Val4_n
Val3_1 Val5_2 Val5_3 Val5_n
I tried using the Group By function, but I had to write out each column's name (which gets very frustrating), I was hoping for something along the lines of:
SELECT MyTable.* FROM MyTable WHERE count(MyTable.Col1) OVER() > 1
Obviously, this didn't work, but how could I do something along those lines??
Thanks!!!
You can use a subquery:
select *
from mytable t1
inner join
(
select count(col1) Total, col1
from mytable
group by col1
having count(col1) > 1
) t2
on t1.col1 = t2.col1
See SQL Fiddle with Demo
Or you can use count(*) over():
select *
from
(
select *,
count(*) over(partition by col1) tot
from mytable
) src
where tot > 1
See SQL Fiddle with Demo
I have a sql query that I run against a sql server database eg.
SELECT * FROM MyTable WHERE Id = 2
This may return a number of records or may return none. If it returns none, I would like to alter my sql query to return a default record, is this possible and if so, how? If records are returned, the default record should not be returned. I cannot update the data so will need to alter the sql query for this.
Another way (you would get an empty initial rowset returned);
SELECT * FROM MyTable WHERE Id = 2
IF (##ROWCOUNT = 0)
SELECT ...
SELECT TOP 1 * FROM (
SELECT ID,1 as Flag FROM MyTable WHERE Id = 2
UNION ALL
SELECT 1,2
) qry
ORDER BY qry.Flag ASC
You can have a look to this post. It is similar to what you are asking
Return a value if no rows are found SQL
I hope that it can guide you to the correct path.
if not exists (SELECT top 1 * FROM mytable WHERE id = 2)
select * from mytable where id= 'whatever_the_default_id_is'
else
select * from mytable where id = 2
If you have to return whole rows of data (and not just a single column) and you have to create a single SQL query then do this:
Left join actual table to defaults single-row table
select
coalesce(a.col1, d.col1) as col1,
coalesce(a.col2, d.col2) as col2,
...
from (
-- your defaults record
select
default1 as col1,
default2 as col2,
...) as d
left join actual as a
on ((1 = 1) /* or any actual table "where" conditions */)
The query need to return the same number of fields, so you shouldn't do a SELECT * FROM but a SELECT value FROM if you want to return a default value.
With that in mind
SELECT value FROM MyTable WHERE Id = 2
UNION
SELECT CASE (SELECT count(*) FROM MyTable WHERE Id = 2)
WHEN 0 THEN 'defaultvalue'
END