I have the below sample code. Assuming I do not know if a particular column exists in a table or not, how could I write the query in a way that I can default the column value to 'Not available' if the column doesn't exist in the table?
Example:
select COL1, COL2,
CASE
WHEN OBJECT_ID('COL3') IS NULL THEN 'Not Available'
ELSE COL3
END AS COL3
from TABLE1
Thanks in advance.
This is quite tricky to do (without dynamic SQL), but there is a way by playing with the scoping rules in SQL. You can do this assuming you have a unique or primary key in the table:
select t1.col1, t1.col2,
(select col3 -- no alias!
from table1 tt1
where tt1.id = t1.id -- the primary/unique key
) col3
from table1 t1 cross join
(values ('Not Available')) v(col3) -- same name
The subquery will fetch col3 from the table1 in the subquery if it exists. Otherwise it will reach out and find col3 from the values() clause.
Related
I am attempting to UPDATE the values of a column in one table based on the count of values in a source table. I am using Teradata Aster.
When I submit the following correlated subquery, I get an error stating the column does not exist despite verifying that it does exist.
UPDATE table2
SET column =
(
SELECT count(*)
FROM table1
WHERE table2.column = table1.column
)
I feel there is something idiosyncratic about Aster, but I'm not certain.
You could use below query for simple column update from another table.
UPDATE table1
SET col2 = table2.col2
FROM table2
WHERE table1.col1 = table2.col1;
and for aggregate function in update query you could use below query.
UPDATE table1
SET col2 = table2.col2
FROM (select col1, count(col2) col2 from table2 group by col1 ) table2
WHERE table1.col1 = table2.col1;
Both the queries works fine for me.
I am trying to delete duplicate records using SQL statement. I am using MS Access 2010. Here is my statement:
DELETE * FROM table1 where not exists (SELECT min(col1) FROM table1 GROUP BY col2, col3 );
Even though the nested Select statement returns a subset of the records of table1, when I execute the delete statement, it deletes no (0) records.
You need a correlation clause. I'm not sure what the data looks like, but this should work:
DELETE *
FROM table1
WHERE col1 <> (SELECT MIN(t1.col1)
FROM table1 as t1
WHERE t1.col2 = table1.col2 AND t1.col3 = table1.col3
);
I suspect that you are trying for:
DELETE *
FROM table1
WHERE col1 NOT IN (SELECT MIN(col1) FROM table1 GROUP BY col2, col3);
This will also work, assuming that col1 is unique across all rows (the first version will work as long as col1 is unique for any pair of col2/col3 values).
I have an insert statement like the following which gets sytax error of "the multi-part identifier "t2.Col1" could not be bound.". I over simplified the statement and it looks like below:
INSERT INTO dbo.T1
(
Col1,
Col2,
Col3
)
SELECT
t2.Col1,
SUBSTRING(aCase.CaseColumn, 0, CHARINDEX('%', aCase.CaseColumn)), --I expect this line gets the value "2"
SUBSTRING(aCase.CaseColumn, CHARINDEX('%', aCase.CaseColumn) + 1, LEN(aCase.CaseColumn) - CHARINDEX('%', aCase.CaseColumn)) --I expect this line gets the value "3"
FROM
dbo.T2 t2
LEFT JOIN
(
SELECT
CASE --I have hundreds of WHEN conditions below and need to access the parent T2 tables' properties
WHEN t2.Col1 = 1 THEN '2%3' --This line has a syntax error of "the multi-part identifier "t2.Col1" could not be bound."
END AS CaseColumn
)
AS aCase ON 1 = 1
The reason I use LEFT JOIN with CASE is that I have hundreds of conditions for which I need to select different values for different columns. I don't want to repeat the same CASE statements over and over again for all of the columns. Therefore, I use a single CASE which concatenates the values with a delimiter and then I parse that concatenated string and put the appropriate values in it's place.
What you could do is use OUTER APPLY, as it allows your dbo.T2 and the aCase resultset to be related, like this:
INSERT INTO dbo.T1
(
Col1,
Col2,
Col3
)
SELECT
1,
SUBSTRING(aCase.CaseColumn, 0, CHARINDEX('%', aCase.CaseColumn)), --I expect this line gets the value "2"
SUBSTRING(aCase.CaseColumn, CHARINDEX('%', aCase.CaseColumn) + 1, LEN(aCase.CaseColumn) - CHARINDEX('%', aCase.CaseColumn)) --I expect this line gets the value "3"
FROM
dbo.T2 t2
OUTER APPLY
(
SELECT
CASE --I have hundreds of WHEN conditions below and need to access the parent T2 tables' properties
WHEN t2.Col1 = 1 THEN '2%3'
END AS CaseColumn
)
AS aCase ON 1 = 1
That is because the result of the subquery is not indipendent itself, it has to be defined based on the values of the dbo.T2 table.
Read more about OUTER APPLY and CROSS APPLY on this thread.
Number 3, "Reusing a table alias" is similiar to your case and the article linked to it perfectly explains how to use cross apply/outer apply in these cases.
When using a join to a subquery, inside that subquery it doesn't know what t2 is, unless you select from a table aliased as t2 in that subquery.
And you could change that LEFT JOIN to an OUTER APPLY.
But you don't really need to JOIN or OUTER APPLY in this case.
Just select from T2 with the CASE in the subquery.
INSERT INTO dbo.T1
(
Col1,
Col2,
Col3
)
SELECT
Col1,
SUBSTRING(CaseColumn, 1, CHARINDEX('%', CaseColumn)-1),
SUBSTRING(CaseColumn, CHARINDEX('%',CaseColumn)+1, LEN(CaseColumn))
FROM
(
SELECT
Col1,
CASE Col1
WHEN 1 THEN '2%3'
-- more when's
END AS CaseColumn
FROM dbo.T2 t2
) q
Note how the CASE and the SUBSTRING's were changed a little bit.
Btw, personally I would just insert the distinct Col1 into T1, and just update Col2 and Col3 in that reference table manually. That could prove to be faster than writing those hundreds conditions. But then again, you did say this was simplified a lot.
I try to execute the following query but it doesn't get any data although it should get one row :
select * from [DB1.table1] where col1 not in (select col2 from DB2.table2)
col1,col2 are of type varchar
why it doesn't work ?
"Doesn't work" isn't exactly a good description of your problem, but in nearly all cases this is caused by the sub-select returning NULL values.
You probably want this:
select * from [DB1.table1]
where col1 not in (select col2 from DB2.table2 where col2 is not null);
The comparison with NULL always yield "undefined" and thus if at least one row from the sub-select contains a NULL in the col2 column the whole expression is "undefined". As undefined not "true", the whole query doesn't return anything.
If you have NULLs in col2 in table2, you'll get the behaviour you describe:
create table table2 (
col2 varchar(10) null
)
insert into table2 (col2) values ('abc'),(null)
create table table1 (
col1 varchar(10) null
)
insert into table1 (col1) values ('abc'),('def')
select * from table1 where col1 not in (select col2 from table2)
Produces no rows. This is because the result of NOT IN becomes UNKNOWN once a NULL comparison occurs.
You can fix it with:
select * from table1 where col1 not in (select col2 from table2 where col2 is not null)
If that's the correct logic for your situtation.
As others have already pointed to the reason that cause this issue, you can achieve the same results, using LEFT JOIN and it safe than the predicate IN with the NULL vlaues:
select t1.*
from [DB1.table1] AS T1
LEFT JOIN DB2.table2 AS t2 ON t1.col1 = t2.col2
where t1.col2 IS NULL;
A table called table1 has a field called field1 with null values in it. This query does not return any rows:
SELECT *
FROM table1
WHERE field1 NOT IN
(
SELECT field1
FROM table1
)
I know there are better ways of writing this query. What causes this behaviour i.e. using not in with a field that contains null values.
OK, I might be missing the point here, but one way to rephrase your query is:
Step 1: Take all values of table1.field1.
Step 2: Return all table1 rows whose field1's value isn't among the values obtained in Step 1.
Surely this always returns the empty set?
In assumption that there is primary key field exists in table, you may use this script:
select
t1.*
from
dbo.Table1 as t1
where
t1.field1 = 'Value1'
and not exists( select 1 from Table1 as t2 where t1.ID != t2.ID and t2.field1 = 'Value2')