How to update a column with different value using simple Join statement? - sql

I have two tables and i am using a simple join condition between them.
I need to find the common values and updated the String(Success) into the column.
input_table1:
ID || Name || output
1 || ABS || Null
2 || ADF || NULL
3 || AQS || Null
4 || ATF || NULL
5 || APS || Null
6 || AMF || NULL
Input_table2:
ID || Name
1 || ABS
2 || ADF
6 || AMF
Output_table:This is the output I need.
ID || Name || output
1 || ABS || Success
2 || ADF || Success
3 || AQS || Null
4 || ATF || NULL
5 || APS || Null
6 || AMF || Success.
This is the query i am using and this is the error is am receiving
An expression of non-boolean type specified in a context where a condition is expected, near 'Then'.
update .[dbo].[InputTable1]
set Output=
case when (
select INT.ID
from [dbo].[input_table1] INT
join [dbo].[input_table2] SHB
on INT.ID=SHB.ID
) Then 'Success' Else Null End

your query should simply be
update INT
set Output= 'Success'
FROM
[dbo].[input_table1] INT
join [dbo].[input_table2] SHB
on INT.ID=SHB.ID
See working demo

...CASE WHEN <condition> = <value> THEN....
You are missing <value> I suspect you need IS NOT NULL after your query.
That said, it is not efficient. DhruvJoshi is better

I would use EXISTS and FROM behind UPDATE for that
UPDATE it
SET Output = (CASE WHEN exists(
SELECT 1
FROM [dbo].[input_table2] SHB
WHERE it.ID=SHB.ID)
THEN 'Success' ELSE Null END)
FROM [dbo].[InputTable1] it

You can just try this :
UPDATE
InputTable1
SET
Output='Success'
FROM
InputTable1
JOIN InputTable2 ON
InputTable1.ID=InputTable2.ID
Only joined rows will be updated

Related

How to concatenate multiple columns where value may be be NULL

I need to pull a query from multiple columns from a table. Some rows will have data in one column, others will have two, three, and even four.
I tried to use this construct:
SELECT person_uid,('(' || major || NVL((',' ||second_major), '') || NVL((',' ||third_major), '') || NVL(',' ||fourth_major, '') || ')' ) AS MAJORS FROM academic_study
But the result would be like this:
6231 (BUMG,BUMK,,)
19091 (TDST,TDPG,,)
I need the parentheses, but not the trailing commas.
I could potentially strip out the extra commas in post processing, but I would prefer to do it in the SQL. I am using ORACLE.
You should fix your data model! Storing multiple columns with parallel data is awkward.
One method is:
select person_uid,
( '(' || major ||
(case when second_major is not null then ',' || second_major end) ||
(case when third_major is not null then ',' || third_major end) ||
(case when fourth_major is not null then ',' || fourth_major end) ||
')'
)

Combining a CASE WHEN statement & a column containing strings of type "Column 1 || '_' || Column 2" in Oracle SQL

I have a table consisting of three columns, which are called the following:
1) Month
2) Store_Type
3) City
I need this table to be expanded to contain five columns and the two columns that I wish to be added are detailed below.
Firstly, the query needs to create a new column called Store_Code. The Store_Code columns job is to store a numerical value which corresponds to what type of store it is.
I presume this would done using a CASE WHEN statement of the type:
SELECT Month,Store_Type,City,
CASE
WHEN Store_Type = 'Corner Shop' THEN '1'
WHEN Store_Type = 'Megastore' THEN '2'
WHEN Store_Type = 'Petrol Station' THEN '3'
....
ELSE '10'
END Store_Code
FROM My_Table
After this is complete, I need to create a column known as "Store_Key". The values contained within the Store_Key column need to be of the following form:
"The Month For That Row""The Store Type For That Row""The City associated with that row"_"The Store Code for that row"
I imagine the best way to create this column would be to use a query similar to the following:
SELECT (My_Table.Month || '_' || My_Table.Store_Type || '_' || My_Table.City || '_' ||
My_Table.Store_Code)
FROM My_Table
What I need is for these two separate queries to be combined into one query. I imagine this could be done by sub-setting the different SELECT queries but I am open to and grateful for any alternative solutions.
Thank you for taking the time to read through this problem and all solutions are greatly appreciated.
Do the case expression part inside a derived table (the subquery):
SELECT (My_Table2.Month || '_' || My_Table2.Store_Type || '_' || My_Table2.City || '_' ||
My_Table2.Store_Code)
FROM
(
SELECT Month,Store_Type,City,
CASE
WHEN Store_Type = 'Corner Shop' THEN '1'
WHEN Store_Type = 'Megastore' THEN '2'
WHEN Store_Type = 'Petrol Station' THEN '3'
....
ELSE '10'
END Store_Code
FROM My_Table
) My_Table2
If this is you trying to populate your new columns, then you need an update statement. I would use two updates to ensure you get the store_case committed for your store_code. Otherwise if you're deriving it in real time, the subquery select answer would be the way to go.
update my_table
set store_case =
case store_type
when 'Corner Shop' then 1
when 'Megastore' THEN 2
when 'Petrol Station' THEN 3
...
else 10
end case;
commit;
update my_table
set store_code = Month || '_' || to_char(Store_Type) || '_' || City || '_' || Store_Code;
commit;
Why to use sub query? It can be done within single query as following:
SELECT My_Table.Month || '_' || My_Table.Store_Type || '_' || My_Table.City || '_' ||
CASE
WHEN Store_Type = 'Corner Shop' THEN '1'
WHEN Store_Type = 'Megastore' THEN '2'
WHEN Store_Type = 'Petrol Station' THEN '3'
....
ELSE '10'
END as result
FROM My_Table
or you can use DECODE function as following:
SELECT My_Table.Month || '_' || My_Table.Store_Type || '_' || My_Table.City || '_' ||
DECODE(Store_Type,
'Corner Shop', '1',
'Megastore', '2',
'Petrol Station', '3'
....,
'10') -- this is default value same as else part of the case statement
as result
FROM My_Table
Cheers!!

Optimize long running select query against Oracle database

I'm not an DBA expert, we have an existing Oracle query to extract data for a particular day , the problem we've is if the business volume for a day is extremly large, the query takes 8+ hours and timedout. We cannot do optimization inside the database itself, then how do we usually handle extreme case like this? I've pasted the query below with content masked to show the SQL structure, looking for advises on how to optimizae this query or any alternative way to avoid timeout.
WHENEVER SQLERROR EXIT 1
SET LINESIZE 9999
SET ECHO OFF
SET FEEDBACK OFF
SET PAGESIZE 0
SET HEADING OFF
SET TRIMSPOOL ON
SET COLSEP ","
SELECT co.cid
|| ',' || DECODE(co.cid,'xxxxx','xxxx',null,'N/A','xxxxx')
|| ',' || d.name
|| ',' || ti.rc
|| ',' || DECODE(cf.side_id,1,'x',2,'xx',5,'xx','')
|| ',' || cf.Quantity
|| ',' || cf.price
|| ',' || TO_CHAR(time,'YYYY-mm-dd hh24:mi:ss')
|| ',' || DECODE(co.capacity_id,1,'xxxx',2,'xxxx','')
|| ',' || co.type
|| ',' || cf.id
|| ',' || CASE
WHEN (cf.account_id = xxx OR cf.account_id = xxx) THEN SUBSTR(cf.tag, 1, INSTR(cf.tag, '.')-1) || '_' || ti.ric || '_' || DECODE(cf.side_id,1,'xx',2,'xx',5,'xx','')
WHEN INSTR(cf.clientorder_id, '#') > 0 THEN SUBSTR(cf.clientorder_id, 1, INSTR(cf.clientorder_id, '#')-1)
ELSE cf.clientorder_id
END
|| ',' || co.tag
|| ',' || t.description
|| ',' || CASE
WHEN cf.id = xxx THEN 'xxxx'
ELSE (SELECT t.name FROM taccount t WHERE t.account_id = cf.account_id)
END as Account
FROM clientf cf, tins ti, thistory co, tdk d, tra t
WHERE cf.sessiondate = TO_DATE('xxxxxx','YYYYMMDD')
AND cf.orderhistory_id = co.orderhistory_id
AND cf.reporttype_id = 1
AND ti.inst_id = cf.inst_id
AND (ti.rc LIKE '%.xx' or ti.rc LIKE '%.xx' or ti.rc LIKE '%.xx' )
AND d.de_id = t.de_id
AND t.tr_id = co.tr_id
AND nvl(co.type_id,0) <> 3
AND cf.trid not in (SELECT v2.pid FROM port v2 WHERE v2.sessiondate = cf.sessiondate AND v2.exec_id = 4)
ORDER BY co.cid, time, cf.quantity;
I would firstly talk to the people who need the output of this query and ask them about the report and each individual column. Sometimes, some columns are not needed any more, sometimes the whole report. 8+ hours runtime is a good bargaining point ;-)
Next, I would put the original query to one side and start build an test query from scratch, bit by bit, for instance starting with clientf, taking all it's columns in the WHERE clause:
SELECT *
FROM clientf SAMPLE (0.1) cf
WHERE cf.sessiondate = TO_DATE('xxxxxx','YYYYMMDD')
AND cf.reporttype_id = 1;
If that's ok, I'd increase the sample size until 99%. If the runtime is already to long, you might suggest an index on clientf.sessiondate (or may be on clientf.reporttype_id, but that's unlikely helpful as it looks like to have too few distinct values).
Once that is done, I'd join the first table:
SELECT *
FROM clientf SAMPLE (0.1) cf
WHERE cf.sessiondate = TO_DATE('xxxxxx','YYYYMMDD')
AND cf.reporttype_id = 1
AND cf.trid NOT IN (SELECT v2.pid
FROM port v2
WHERE v2.sessiondate = cf.sessiondate
AND v2.exec_id = 4);
I'd compare NOT IN and WHERE NOT EXISTS, not expecting much differences.
Then I'd join the next table (prefering personally ANSI syntax), again starting with a small sample, again adding it's columns to the where clause:
SELECT *
FROM clientf SAMPLE (0.1) cf
FROM thistory co
ON cf.orderhistory_id = co.orderhistory_id
WHERE cf.sessiondate = TO_DATE('xxxxxx','YYYYMMDD')
AND cf.reporttype_id = 1
AND nvl(co.type_id,0) <> 3
AND cf.trid NOT IN (SELECT v2.pid
FROM port v2
WHERE v2.sessiondate = cf.sessiondate
AND v2.exec_id = 4);
I'd play around replacing nvl(co.type_id,0)<>3 with (co.type_id <>3 OR co.type_id IS NULL), monitoring carefully that the result is logically the same.
And so on...

Oracle 12c Concatenate with brackets where nulls are involved

We have a set of columns within a table we need to concatenate, and we need brackets around the third, fourth, fifth and sixth value, but also need nothing to appear if the column is null.
SELECT "ID",
NVL(PART || '.'|| SECTION ||'(' ||SUB1||')'|| '(' ||SUB2|| ')' || '('||SUB3||')' || '('||SUB4||')', '') as concatenated
FROM table1;
Places the values exactly right as long as there are values. When any one or more columns return null, we are getting an empty set of brackets for each null value.
Such as: 113.203()()()() when there are four null values
in this case we would need: 113.203
Or 113.450(h)(2)(iv)() when there is one null value.
here the desired results
would be 113.450(h)(2)(iv)
How can I change the script to leave out all the empty brackets when a null value is returned?
Thank you.
Hmmm, I think you want:
select id,
(part || '.' || section ||
(case when sub1 is not null then '(' || sub1 || ')' end) ||
(case when sub2 is not null then '(' || sub2 || ')' end) ||
(case when sub3 is not null then '(' || sub3 || ')' end) ||
(case when sub4 is not null then '(' || sub4 || ')' end)
) as concatenated
from table1;

Using Index for joining two tables when FK field is NULL

We started to maintain a new project that uses SQL Server and there are some problems regarding to the data in some tables as explained below. There are 2 tables called Employee and Pass and the Pass table keeps the in and out of every Employee.
Employee
|| ID || Name || CardNo ||
======================================
|| 1 || John || 101 ||
|| 2 || Christof || 102 ||
|| 3 || Jurgen || 103 ||
|| 4 || Jose || 104 ||
|| 5 || Mary || 105 ||
Pass
|| ID || EmployeeID || CardNo ||
======================================
|| 1 || NULL || 101 ||
|| 2 || NULL || 105 ||
|| 3 || NULL || 103 ||
|| 4 || NULL || 101 ||
|| 5 || NULL || 102 ||
|| 6 || NULL || 104 ||
|| 7 || NULL || 104 ||
|| 8 || NULL || 103 ||
|| 9 || NULL || 105 ||
|| 10 || NULL || 101 ||
On the other hand, as the EmployeeID column of the Pass table is empty for every pass, we have to use CardNo column in order to join two tables.
But using the JOIN clause as shown below causes the query to be executed more time and I think there might be a better way by using index, etc. instead of PK to optimize the query. We have tried to create index, but could not create for CardNo column.
Could you please clarify us on how to fix the problem? Thanks...
SELECT *
FROM Pass p
LEFT JOIN Employee e ON RIGHT(e.CardNo, 8) = RIGHT(p.CardNo, 8) --I have to trim card no as the digit sizes are different
Update :
I tried to apply the following scripts, but only this part is worked:
alter table Pass add cardno8 as RIGHT(CardNo, 8);
alter table Employee add cardno8 as RIGHT(CardNo, 8);
And this part gives error: "Column 'cardno8' in table 'Pass' is of a type that is invalid for use as a key column in an index."
create index idx_tEvent_cardno8 ON Pass(cardno8);
create index idx_tEmployee_cardno8 ON Employee (cardno8);
Any idea?
If the problem is the performance of the query, then you simply need an index on Employee(CardNo):
create index idx_employee_cardno on employee(cardno);
If you are interested in only one or two other columns (such as name or id), you can add them to the index after cardno.
The only reason that I can think of (apart from permissions) to explain why index creation would fail is that cardno has the wrong type. To quote the documentation:
Columns that are of the large object (LOB) data types ntext, text,
varchar(max), nvarchar(max), varbinary(max), xml, or image cannot be
specified as key columns for an index.
That seems unlikely given the sample data. If this is an issue, then change the type to something more appropriate (or use a computed column for the same purpose).
Also, your query should use qualified column names everywhere (or you'll get an error):
SELECT *
FROM Pass p LEFT JOIN
Employee e
ON e.CardNo = p.CardNo;
--------^