SQL Oracle - CASE WHEN for separately ID's [closed] - sql

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have some (thousands ;)) ID's and I'm trying check their relationship separately. But I have problem with checking relationship for each ID independently. Actualy my code check this for all ID`s beetwen them..
Table for example
ID Service
1 A
1 A1
2 A
2 B
3 A
3 A1
SQL code
SELECT a.ID, a.service,
CASE
WHEN a.service IN ('A','A1') THEN 'Yes'
ELSE 'No'
END
FROM t1 a
Output
ID Service RELATION
1 A YES
1 A1 YES
2 A NO
2 B NO
3 A YES
3 A1 YES

First, you should sort your table according to service alphabetically.
Then create an array and populate it with all the services:
DECLARE
CURSOR c_t1 is
SELECT service FROM t1;
type c_list is varray (6) of t1.service%type;
service_list c_list := c_list();
counter integer :=0;
BEGIN
FOR n IN c_t1 LOOP
counter := counter + 1;
service_list.extend;
service_list(counter) := n.service;
dbms_output.put_line('Service('||counter ||'):'||service_list(counter));
END LOOP;
END;
/
Then iterate through your table values:
DECLARE
v_count number DEFAULT 0;
BEGIN
FOR i IN (SELECT t1.ID, t1.service FROM t1)
LOOP
FOR j IN (service_list.COUNT)
LOOP
CASE
WHEN t1.service IN (service_list[i], service_list[i+1]) THEN 'Yes'
ELSE 'No'
END
v_COUNT := v_COUNT + 1;
END LOOP;
END LOOP;
DBMS_OUTPUT.PUT_LINE(v_COUNT);
END;
/

The following query works though I'm not sure how it would perform.
WITH a1
AS (SELECT id, 1 AS here
FROM services
WHERE service = 'A1')
, a
AS (SELECT id, 1 AS here
FROM services
WHERE service = 'A')
SELECT driver.id
, driver.service
, CASE
WHEN NVL(a1.here, 0) + NVL(a.here, 0) > 1 THEN 'YES'
ELSE 'NO'
END
FROM services driver
LEFT OUTER JOIN a1 ON a1.id = driver.id
LEFT OUTER JOIN a ON a.id = driver.id

But I have problem with checking relationship for each ID
independently
That is why it is suggested to you to create a new table storing all the unique relationships between the services. This gives you a better handle to compare the relations and give you the desired output.
You should start by creating the relationship table which stores values like this.
|rid| S1 | S2 |
--- |----|----|
|1 | A | A1 |
Now, to generate your desired output, you should first use a self join to get the pairs of relations with common IDs .
SELECT a.id,
a.service,
b.service
FROM t1 a
join t1 b
ON ( a.service != b.service
AND a.id = b.id ) ;
Once you have got such combinations, all you would need is to check if that combination of relation exists using an OUTER JOIN with relationship table, which will help you to get the output as "YES" or "NO" based on the existence.
SELECT a.id,
b.service,
CASE
WHEN r.id IS NULL THEN 'NO'
ELSE 'YES'
END AS relation
FROM t1 a
join t1 b
ON ( a.service != b.service
AND a.id = b.id )
left join rel r
ON ( ( r.s1 = a.service
AND r.s2 = b.service )
OR ( r.s2 = a.service
AND r.s1 = b.service ) );
Demo

I would use window function :
select t1.*, (case when sum(case when service not in ('A', 'A1') then 1 else 0 end) over (partition by id) = 0
then 'yes' else 'no'
end) as Relation
from t1;

this will work and you have to use decode function for it:
create table ex2(
no1 number,
no2 varchar(20));
insert into ex2 values(1, 'A');
insert into ex2 values(1 , 'A1');
insert into ex2 values(2 , 'A');
insert into ex2 values(2 , 'B');
insert into ex2 values(3 , 'A');
insert into ex2 values(3 , 'A1');
select * from ex2;
SELECT no1, no2 ,
decode(no2,'A','yes','A1','yes','no')
FROM ex2;
output:
1 A yes
2 A yes
2 B no
3 A yes
3 A1 yes
1 A1 yes
for your table query is :
SELECT ID, service ,
decode(service,'A','yes','A1','yes','no')
FROM ex2;

Related

Join two tables on multiple conditions Using Oracle SQL

I have a 2 Tables with below structures
Table 1-- Containing Values like this.
OTHER_CODE
CAPACITY_CODE
Result
A
1
A
5
A
9
A
(null)
B
2
B
6
B
2
Table_2- With Values Like
OTHER_CODE
CAPACITY_CODE
Result
A
1
A
A
5
B
A
(null)
C
A
ELSE
D
B
ALL
E
(null)
ALL
F
I need to Join Table_1 with Table_2 on basis of columns OTHERCODE and CAPACITYCODE and update values in Column Result of Table**1 **using a Merge statement.
I need to handle and match Values based on ELSE and ALL values too.
Check for Direct Match
Check if ALL or ELSE condition
The Final TABLE_1 must look like
OTHER_CODE
CAPACITY_CODE
Result
Explanation
A
1
A
Direct Join
A
5
B
Direct Join
A
9
D
Satsifying ELSE condition
A
(null)
C
Direct join with NVL handling
B
2
E
As Value for CapacityCode in TableB is ALL
B
6
E
As Value for CapacityCode in TableB is ALL
B
2
E
As Value for CapacityCode in TableB is ALL
I Tried Joining both the tables but the was unable to satisfy Else and ALL conditions. Hope if someone can help me on this.
There are Several **Result ** Columns like , Result 1 ,2 in both tables which needs to be updated using the same logic.
Thanks in Advance.
here is a fiddle to work on https://dbfiddle.uk/FMKdWzQT
I got the query working. by using a case statement and assigning a number so I could use max then I just remove the number.
SELECT a.other_code,
a.capacity_code,
(
SELECT SUBSTR(max(
CASE WHEN b.other_code = a.other_code AND a.capacity_code = b.capacity_code THEN concat('3',b.myresult)
WHEN b.other_code = a.other_code AND a.capacity_code is null and b.capacity_code is null THEN concat('2',b.myresult)
WHEN b.other_code = a.other_code AND b.capacity_code in ('ELSE', 'ALL') THEN concat('1',b.myresult)
else null end),2)
FROM table2 b ) as myresult
FROM table1 a
however I can not get the update to work. I tried a merge it is give me the unstable row error and I tried an update select but that is giving me single row subquery error so maybe someone else can take a look at the fiddle. here was my attempt at the update.
UPDATE table1
SET myresult = (
SELECT myresult
FROM (
SELECT a.other_code,
a.capacity_code,
(
SELECT SUBSTR(max(
CASE WHEN b.other_code = a.other_code AND a.capacity_code = b.capacity_code THEN concat('3',b.myresult)
WHEN b.other_code = a.other_code AND a.capacity_code is null and b.capacity_code is null THEN concat('2',b.myresult)
WHEN b.other_code = a.other_code AND b.capacity_code in ('ELSE', 'ALL') THEN concat('1',b.myresult)
else null end),2)
FROM table2 b ) as myresult
FROM table1 a
)t2
WHERE table1.other_code = t2.other_code and nvl(table1.capacity_code,'x') = nvl(t2.capacity_code,'x')
);

sql function case returns more than one row

Going to use this query as a subquery, the problem is it returns many rows of duplicates. Tried to use COUNT() instead of exists, but it still returns a multiple answer.
Every table can only contain one record of superRef.
The below query I`ll use in SELECT col_a, [the CASE] From MyTable
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = myTable.sysno AND A_specAttr = 'value')
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo WHERE C_superRef = myTable.sysno AND b_type = 2)
THEN 2
ELSE (SELECT C_intType FROM C
WHERE C_superRef = myTable.sysno)
END
FROM A, B, C
result:
3
3
3
3
3
3...
What if you did this? Because Im guessing you are getting an implicit full outer join A X B X C then running the case statement for each row in that result set.
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = 1000001838012)
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo AND C_superRef = 1000001838012 )
THEN 2
ELSE (SELECT C_type FROM C
WHERE C_superRef = 1000001838012)
END
FROM ( SELECT COUNT(*) FROM A ) --This is a hack but should work in ANSI sql.
--Your milage my vary with different RDBMS flavors.
DUAL is what I needed, thanks to Thorsten Kettner
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = 1000001838012)
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo AND C_superRef = 1000001838012 )
THEN 2
ELSE (SELECT C_type FROM C
WHERE C_superRef = 1000001838012)
END
FROM DUAL

Insert case when into table from joined table

I'm new to SQL and I'm having some trouble solving a problem. I'm rewriting a script where I can match with customers who have received an email. Previously I have been using session tables as below:
DECLARE GLOBAL TEMPORARY TABLE EMAIL_SENDS
(
ACCOUNT_NUMBER INT
)
WITH REPLACE
ON COMMIT PRESERVE ROWS
;
INSERT INTO SESSION.EMAIL_SENDS
SELECT ACCOUNT_NUMBER
FROM SENT_DATA A
JOIN MAIN_TABLE B
ON A.CLIENT_ID_SUBKEY = B.CUST_ID
OR A.CLIENT_ID_SUBKEY = B.OLD_ID
WHERE SEND_ID = 123456
GROUP BY ACCOUNT_NUMBER
;
Then when pulling the data I have just used CASE WHEN C.ACCOUNT_NUMBER IS NOT NULL THEN 1 ELSE 0 END joining the MAIN_TABLE with the EMAIL_SENDS to flag who has and hasn't received the email.
However I would like to improve the process, and add a column to the MAIN_TABLE stating who has received an email and who hasn't.
This is my script so far:
ALTER TABLE MAIN_TABLE
ADD EMAILED INT
;
INSERT INTO MAIN_TABLE
SELECT EMAILED
CASE WHEN ACCOUNT_NUMBER IS NOT NULL THEN 1 ELSE 0 END
FROM (SENT_DATA A
JOIN MAIN_TABLE B
ON A.CLIENT_ID_SUBKEY = B.CUST_ID
OR A.CLIENT_ID_SUBKEY = B.OLD_ID
WHERE SEND_ID = 123456
GROUP BY ACCOUNT_NUMBER
)
;
As I'm new to SQL I'm not able to figure out where I'm going wrong (even though it's probably obvious to anyone proficient at it).
try this. replace column names from main table to with this (EMAILED,ACCOUNT_NUMBER)
INSERT INTO MAIN_TABLE (EMAILED,ACCOUNT_NUMBER)
SELECT EMAILED,
CASE WHEN ACCOUNT_NUMBER IS NOT NULL THEN 1 ELSE 0 END
FROM (SENT_DATA A
JOIN MAIN_TABLE B
ON A.CLIENT_ID_SUBKEY = B.CUST_ID
OR A.CLIENT_ID_SUBKEY = B.OLD_ID
WHERE SEND_ID = 123456
GROUP BY ACCOUNT_NUMBER
)
;

Return all locations, users, and roles where a user has 'X' role in each location (SQL Server)

I am needing to write a query to identify all locations, users, and roles from a table where a user has 'X' role in each location.
The table has three columns (A = location, b = user, c = role).
A is a varchar, b is an INT, and c is an INT. Suppose the table contains the following:
A B C
location 1 1 1
location 1 1 2
location 2 1 1
location 1 2 1
location 1 2 2
location 3 2 1
I am wanting to return all locations (A), users (B), and roles (C) where the location (A) and user (B) contains roleID 2 in C.
The expected result from the above table is:
A B C
location 1 1 1
location 1 1 2
location 1 2 1
location 1 2 2
Thanks in advance!
SELECT *
FROM YourTable t1
WHERE EXISTS (
SELECT 1
FROM YourTable t2
WHERE t1.A = t2.A
and t1.B = t2.B
and t2.C = 2
)
What you want is called "relational division". The only problem is that your textual description contradicts with your desired output. For the output provided, the wording should be "get all data for locations where all users are members of the role 2", which is quite different. Anyway:
declare #t table (
LocationId varchar(20) not null,
UserId int not null,
RoleId int not null
);
insert into #t values
('location 1',1, 1),
('location 1',1, 2),
('location 2',1, 1),
('location 1',2, 1),
('location 1',2, 2),
('location 3',2, 1);
-- What you have said
select t.*
from #t t
inner join (
select c.LocationId, c.UserId
from #t c
where c.RoleId = 2
group by c.LocationId, c.UserId
having count(*) = (select count(distinct cn.LocationId) from #t cn)
) sq on sq.UserId = t.UserId and sq.LocationId = t.LocationId;
-- What you seem to need
select *
from #t r
where exists (
select t.LocationId
from #t t
where t.LocationId = r.LocationId
group by t.LocationId
having count(distinct t.UserId) = count(distinct case t.RoleId when 2 then t.UserId end)
);
(I can't operate in terms like A, B, C - it hobbles my mind. So above is a proper table.)

SQL Query to check if student1 has a course with student 2

I have one table and I need to check if two users, for whom I have the IDs (e.g. 20 and 21) share the same course, just true or false.
Table: jos_gj_users
Columns: id_user, id_group
Data Example: (20; 4)
(20; 5)
(20; 6)
(21; 6)
(21; 7)
The data above shows that user 20 and user 21 share the course 6 but how do I get this with SQL just by entering the IDs and without looping through the results with PHP?
Try a self-join:
SELECT T1.id_group
FROM jos_gj_users T1
JOIN jos_gj_users T2
ON T1.id_group = T2.id_group
WHERE T1.id_user = 20
AND T2.id_user = 21
To just get a "true or false" result you can check from the client to see if at least one row exists in the result set rather than fetching the entire results.
Alternatively you can do it in SQL by wrapping the above query in another SELECT that uses EXISTS:
SELECT CASE WHEN EXISTS
(
SELECT T1.id_group
FROM jos_gj_users T1
JOIN jos_gj_users T2
ON T1.id_group = T2.id_group
WHERE T1.id_user = 20
AND T2.id_user = 21
) THEN 1 ELSE 0 END AS result
This query returns either 0 (false) or 1 (true).
The idea is that you have to join the table to itself. In the first half you look for user 1 and in the second half you look for user 2. And of course only those rows that have the same id_group in both half are relevant:
SELECT count(*)
FROM jos_gj_users As j1, jos_gj_users As j2
WHERE j1.id_user = 20 AND j2.id_user = 21
AND j1.id_group = j2.id_group
This will always return one row with one column: The number of shared courses. If it is 0, they don't share any courses.
You could do it with a subselect:
select id_group
from jos_gj_users
where (id_user = 20)
and id_group in (select id_group from jos_gj_users where id_user = 21)
SELECT COUNT(*) > 0 FROM jos_gj_users WHERE id_user=54321 AND id_group IN ( SELECT id_group FROM jos_gj_users WHERE id_user = 1345 )
This is query that shows users from same groups.
SELECT
*
FROM
jos_gj_users T1
INNER JOIN jos_gj_users T2 ON T1.id_group = T2.id_group
Give this a try - it accepts the input parameters in the first bolded area, and returns a value of TRUE or FALSE via a CASE statement based on the values in the second bolded areas.
SELECT DISTINCT CASE WHEN
(SELECT DISTINCT COUNT(id_group) FROM jos_gj_users WHERE id_user IN (20, 21) GROUP BY id_group
HAVING COUNT(DISTINCT id_user) = 2) IS NOT NULL THEN 'TRUE'
ELSE 'FALSE'
END
FROM jos_gj_users