Update using case and select from different table - tsql

I'm trying to do an SQL update where I want to set the value of the column being updated depending on the value in a second table. The script below shows what I'm trying to do but so far I haven't hit on the correct syntax.
update sometable set name =
case
when (select newid from lookuptable where oldid = name) <> null then newid
else name
end

UPDATE T
SET
T.name = L.newid
FROM sometable T
INNER JOIN lookuptable L
ON L.oldid = T.name
There's no need for a coalesce or an outer join, because you're only interested in updating the rows that match.
Also, when comparing a value to null, you should always use X IS NULL or X IS NOT NULL rather than X = NULL or X <> NULL, because equality (and inequality) operators always return false for null values.

Related

how can I translate a query to CTE?

I'm still having trouble understanding how CTE works.
I'm looking to make an insert. In case of conflict I use the on conflict do nothing but I want it to return the id to me (for the success of the insert or the conflict)
WITH inserted AS (
INSERT INTO fiche(label)
VALUES ('label')
ON CONFLICT (label) DO NOTHING
RETURNING *
)
SELECT * FROM inserted
WHERE NOT EXISTS (SELECT 1 FROM inserted);
Note that
SELECT * FROM some_relation
WHERE NOT EXISTS (SELECT 1 FROM some_relation);
will always give you an empty result. Either some_relation is empty itself or if it is not empty SELECT 1 FROM some_relation is not empty and therefore NOT EXISTS ... always returns false and so no record is matching the WHERE clause.
What you want is to have the VALUES as a CTE. You can then reference the values from your INSERT statement and in a SELECT to compare those values to the result of the RETURNING clause.
WITH
vals AS (
VALUES ('label')
),
inserted AS (
INSERT INTO fiche(label)
SELECT * FROM vals
ON CONFLICT (label) DO NOTHING
RETURNING label, id
)
SELECT
vals.column1,
inserted.id
FROM vals
LEFT JOIN inserted ON vals.column1 = inserted.label
This should give you a row for each row in your VALUES clause and the second column will be NULL if it was not inserted due to a conflict or the inserted ID otherwise.

How to do a select inside an insert using Postgresql?

I am a beginner in postgresql and databases in general. I have a table with a column product_id. Some of the values in that column are null. I need to change those null values to the values from another table.
I want to do something like this:
insert into a(product_id) (select product_id from b where product_name='foo') where product_id = null;
I realize that this syntax doesn't work but I just need help figuring it out.
Assuming your table name is "a" and you have some null product_id, but the othe colums does contain data.
So you need to UPDATE, not to INSERT.
Your Query will be something like this :
Update a
set product_id = select product_id from b where b.product_name = 'foo'
Where product_id is null
be sure that your sub query (select ..from b) return a unique value.
Try below
INSERT INTO a (product_id)
select product_id from b where product_name='foo';
your where condition is wrong after the) bracket I.e. where product_id = null;

add Exists operator in a union sql query

I have two tables that am using union to combine the result-set of them my problem here is Each SELECT statement within UNION must have the same number of columns and data types, I don't have the same number of columns so am creating null columns
select
d.deal_id as order_id,
EXISTS(select * from table1 c where d.user_id = c.user_id) as IsUser, --this returns boolean value
from table 1 c
union
select
cast(o.id as varchar) as order_id,
coalesce('No_user'::text,'0'::text) as IsUser, --i get an error :UNION types boolean and character varying cannot be matched
from table2 o
how can I create a null column in table2 that matches the boolean data type of the table1
how can I create a null column in table2 that matches the boolean data type of the table1
By putting NULL into the SELECT list of the second query.
Generally (in SQL) the datatype for the column is dictated by the first query in the union set and other queries must match. You don't need column aliases for subsequent queries either, but they may help make a query more readable:
select
d.deal_id as order_id,
EXISTS(select * from table1 c where d.user_id = c.user_id) as IsUser, --this returns boolean value
from table 1 c
union
select
cast(o.id as varchar) as order_id,
null --IsUser
from table2 o
If you have a case where the type of the column in the first query is different to what you want in the output, you cast the first column:
select 1::boolean as boolcol
UNION
select true
This will ensure that the column is boolean, rather than giving a "integer and bool cannot be matched". Remember also that, should you need to, NULL can be cast to a type, e.g. select null::boolean as bolcol

Why does postgres group null values?

CREATE TEMP TABLE wirednull (
id bigint NOT NULL,
value bigint,
CONSTRAINT wirednull_pkey PRIMARY KEY (id)
);
INSERT INTO wirednull (id,value) VALUES (1,null);
INSERT INTO wirednull (id,value) VALUES (2,null);
SELECT value FROM wirednull GROUP BY value;
Returns one row, but i would expect two rows since
SELECT *
FROM wirednull a
LEFT JOIN wirednull b
ON (a.value = b.value)
does not find any joins, because null!=null in postgres
According to SQL wikipedia :
When two nulls are equal: grouping, sorting, and some set operations
Because SQL:2003 defines all Null markers as being unequal to one another, a special definition was required in order to group Nulls together when performing certain operations. SQL defines "any two values that are equal to one another, or any two Nulls", as "not distinct".[20] This definition of not distinct allows SQL to group and sort Nulls when the GROUP BY clause (and other keywords that perform grouping) are used.
This wasn't the question:
Because null = null or something = null return unknown not true/false
So:
ON (a.value = b.value)
Doesn't match.

T-SQL WHERE clause - comparing column to itself fails on null columns

I usually use a construct like this to apply filters to columns:
CREATE TABLE test(a int NOT NULL, b int NULL)
--insert some data
INSERT INTO test(a,b) values (1,1)
INSERT INTO test(a,b) values (1,NULL)
declare #a int
declare #b int
set #a = 1
--#b is null at this time
select * from test
where a = #a
and b = isnull(#b,b)
This only selects the first row.
For example, if this was a stored procedure and argument #b was null, I could specify its value to 'enable' it in the where clause, and specify NULL value to select where b=b, which would be true for each column, BUT if there is a NULL value in b column, it does not get selected. Is there a standard way to deal with this? So what should I use in the above example query to select all rows even if b column has null values?
For checking NULL values you need to do it as b is null
You can change query as -
select * from test
where a = #a
and b = isnull(#b,b)
or (#b is null and b is null)