I am writing a query for getting a customer list from database. The query contains a where condition to check customer's email is empty or not.
The original query:
SELECT ID
FROM MAINTABLE m
LEFT JOIN CUSTOMER c
ON m.CUS = c.CUS
WHERE c.EMAIL <> ''
Howevery, in my case. delivery_type is a SSRS parameters and used to represent the email field is empty or not
. If the value is 'A' means the email field is empty, 'B' is not. I have tried below query but it seems totally wrong.
Anyone can help me on this issue?
SELECT ID, CASE WHEN c.EMAIL = '' then 'A' WHEN c.EMAIL <> '' THEN 'B' END 'delivery_type'
FROM MAINTABLE m
LEFT JOIN CUSTOMER c
ON m.CUS = c.CUS
WHERE delivery_type = #delivery_type
WHERE delivery_type = #delivery_type AND (
(#delivery_type = 'A' AND email = '')
OR
(#delivery_type = 'B' AND email <> '')
)
I am working on Postgres and I have two tables vehicles and vehicles_flag. There are no relations between the two tables and hence we can not join two tables to fetch the required data.
The table structure is below (vehicle_flag table may not contain all the id present in the vehicle table) :
[Table structure]
I am writing a function that will accept multiple input parameters. I have to select vehicle id from the vehicle_flag table only if the flag value is true: otherwise, I have to ignore the vehicel_flag table. My aim is to achieve something like this, but turns out the case statement expects scaler output:
select count(id) from vehicles
where
vehicles.id in (case
when #hasbluetooth =1 then (select distinct id from vehicle_flags where flag='bluetooth' and value = '1')
else
(select distinct id from vehicles)
end)
and
vehicles.id in (case
when #hasac =1 then (select distinct id from vehicle_flags where flag='ac' and value = '1')
else
(select distinct id from vehicles)
end)
Kindly suggest any solution to achieve this.
I suspect you want:
select v.*
from vehicle v
left join vehicle_flags vf on vf.id = v.id
group by v.id
having
(#hasbluetooth = 0 or bool_or(vf.flag = 'bluetooth' and vf.value = 1)
and (#hasac = 0 or bool_or(vf.flag = 'ac' and vf.value = 1)
I have a table t with several columns, let's name them a, b and c. I also have a state column which indicates the current state. There is also an id column.
I want to write the following query: update column a always, but b and c only if the application state is still equal to the database state. Here, the state column is used for optimistic locking.
I wrote this query as following:
UPDATE t
SET a = $a$,
b = (CASE WHEN state = $state$ THEN $b$ ELSE b END),
c = (CASE WHEN state = $state$ THEN $c$ ELSE c END)
WHERE id = $id$ AND
(
a != $a$ OR
b != (CASE WHEN state = $state$ THEN $b$ ELSE b END) OR
c != (CASE WHEN state = $state$ THEN $c$ ELSE c END)
)
Here, $id$, $a$, ... are input variables from the application. The second part of the WHERE clause is to avoid updates which do not effectively update anything.
This query works as expected, but is very clumsy. I am repeating the same condition several times. I am looking for a way to rewrite this query in a more elegant fashion. If this was a simple SELECT query, I could do something with a LATERAL JOIN, but I cannot see how to apply this here.
How can I improve this query?
Split the query in two:
UPDATE t
SET a = $a$
WHERE id = $id$
UPDATE t
SET b = $b$,
c = $c$
WHERE id = $id$ AND
state = $state$
If you need atomicity, wrap in a transaction.
This seems a bit cleaner(untested):
WITH src AS (
SELECT $a$ AS a
, (CASE WHEN state = $state$ THEN $b$ ELSE b END) AS b
, (CASE WHEN state = $state$ THEN $c$ ELSE c END) AS c
FROM t
WHERE id = $id$
)
UPDATE t dst
SET a=src.a, b=src.b, c=src.c
FROM src
WHERE dst.id = src.id
AND (src.a, src.b, src.c) IS DISTINCT FROM (dst.a, dst.b, dst.c)
;
EDIT: It Took me a while to realize my fault here: The question obviously targets at a single update, while my answer tried to update many rows. However, if you need to execute this Update for a set of rows you could:
Insert the needed parameters in a temporary table
Join that table within the "t2" subquery
Select it's columns (e.g. tempTable.b As tempB)
Replace the Parameters (e.g. $b$ -> t2.tempB)
.
UPDATE t
SET a=source.a,
b=source.b,
c=source.c
FROM
(
SELECT
id,
a,
(CASE WHEN UpdateCondition THEN $b$ ELSE b END) AS b,
(CASE WHEN UpdateCondition THEN $c$ ELSE c END) AS c
FROM
(
SELECT state = $state$ As UpdateCondition, * FROM t
) As t2
WHERE
id = $id$ AND
(
a != $a$ OR
b != (CASE WHEN UpdateCondition THEN $b$ ELSE b END) OR
c != (CASE WHEN UpdateCondition THEN $c$ ELSE c END)
) AS source
WHERE t.id=source.id;
The Sub query for t2 gives you your state Condition and executes the calculation for it only once per row.
The subquery for "source" gives you the mapped values and filters those without changes.
The only filter you need is on ID = $id
The case statement says don't change it in the update if the state doesn't match, so you don't need to filter it.
EDIT
where Id = $id and a !=$a
Or (state = $state and (b !=b or c!= $c))
If you do any more than that then"always update a" will not necessary be true.
3rd attempt checks for the possibility of a remaining the same, but b or c updating.
I have this 2 tables SupplierOrder and SupplierOrderDetails which are linked by SupplierOrder PK. Now I have this col called isComplete in the SupplierOrder table which I want o update to true once all the values in the SupplierORderDetails table's isComplete are all true for that supplierOrder ID. Please see the attachment for the tables. I have tried myself with this query but I think it could be a better way or more efficient.
SELECT 1
FROM supplierOrder so
inner JOIN supplierOrderdetails sod
ON so.id = sod.supplierOrderID
WHERE so.id = 1
AND sod.isComplete= 1
This should work, I maynot have correct table names but this should work if u change it
UPDATE suplierorder
SET iscomplete = 'true'
WHERE id IN (SELECT suplierorderid
FROM (SELECT suplierorderid,
--case statement to set to 0 if complete and 1 if not complete (i.e any other value null or false)
Sum(CASE
WHEN iscomplete = 'true' THEN 0
ELSE 1
END) AS complete
FROM suplierorderdetails
--make sure we only update the new ones and makes sure that your select records are limited to Just not complete records, so if your tables grow this will make your update statement doesn't take a lot of time
WHERE suplierorderid IN (SELECT id
FROM suplierorder
WHERE iscomplete IS NULL)
--I am grouping on suplierorderid so that we can add all the iscomplete status of each suplierorderid column
GROUP BY suplierorderid) A
--now that the inner query outputs suplierorderid and complete status which will be 0 if everything is complete we are writing below condition
WHERE complete = 0)
All we need is to find supplierOrderID where MIN(isComplete)=1. So it means that ALL isComplete=TRUE
UPDATE supplierOrder SET isComplete=1
WHERE id in
(
SELECT supplierOrderID
FROM supplierOrderdetails
GROUP BY supplierOrderID
HAVING MIN(CAST(isComplete as Int))=1
)
AND
(
(isComplete is NULL ) OR (isComplete = 0)
)
SQLFiddle demo
PS: Since isComplete is a BIT type field you can't use MIN(isComplete) but you can use MIN(CAST(isComplete as Int))
I want to compare a column in table a and table b
If the a value from table a can be found in table b then I want to update another column in table a with a 'yes' and if it cannot be found I want to say 'no'. This is what I have so far:
UPDATE a
set
[CCA Match Org] = CASE WHEN b.[serial] = a.[CSI] THEN 'yes' ELSE 'no' END
My error at the moment says:
The column prefix 'b' does not match with a table name or alias name used in the query.
Assuming the join is on b.[serial] = a.[CSI]:
UPDATE a
SET [CCA Match Org] = CASE WHEN b.[serial] IS NOT NULL
THEN 'yes' ELSE 'no' END
FROM a LEFT OUTER JOIN b
ON b.[serial] = a.[CSI];
This is a quick example, not sure if it will work in your case because you didnt give us more info on the table structures.
UPDATE a SET col='Yes' WHERE a.id IN (SELECT a.id FROM a JOIN b ON a.CSI = b.serial)