How i want make 3 rows of the same primary key into 1 row by checking and choose its value using case - sql

For example here, from this table
key | status
1001 | A
1001 | D
1001 | C
the hierarchy will be C>D>A
If the the stats contain C as the value, the person status will become C in one row. It will be like this:
key | status
1001 | C
it will ignore D and A because it has value C. If it doesn't has C,then it will check for D first before A.
So, how can i do that? I dont how to make the 3 row into 1. I tried using
''' CASE WHEN STATUS IN('C')THEN 'C'
ELSE WHEN STATUS IN('D') THEN 'D'
ELSE WHEN STATUS IN('A') THEN 'A'
END AS STATUS '''
But it give error and still can't make the row into 1

You can try the below -
select key, status
from tablname
order by case when status='C' then 1 when status='D' then 2 when status='A' then 3 else 99 end
FETCH FIRST 1 ROW

You can use analytical function row_number as follows:
Select * from
(Select t.*,
Row_number() over (partition by key order by case when status = 'C' then 1
when status = 'D' then 2
when status = 'A' then 3 end) as rn
From your_table)
Where rn = 1;

Related

Create a new column based on existing columns inside a case statement

Say I have this table t:
id value
1 1 10
2 2 3
3 1 55
4 1 20
5 2 98
When drawing from t I want to add a column value2 that equals value when id == 2, otherwise 0
I tried
select id, value, max(case when id = 2 then value else 0) from t
but it did not work
Not sure why you included a max in your attempt but based on your description, this is all you should need.
select id, value, case when id = 2 then value else 0 end as value2
from t;
It sounds like you want a conditional window aggregate:
select
id,
value,
max(case when id = 2 then value end) over ()
from t;

Return Max ID SQL

I have a table with several rows as mentioned below having same account id :
id account_id id_intern Name Active mobile_no landline_no email
1 0011abs 66654 A yes 098937888 098937888 a#gmail.com
2 0011abs 66655 B yes 098937666 098937666 b#gmail.com
3 0011abs 66656 C no 098937777 098937777 c#gmail.com
4 0011abs 66657 D yes 098937666 d#gmail.com
5 0011abs 66658 E yes 098937111 e#gmail.com
6 0011abs 66659 F yes 098937111 098937665
I am searching for script that can return me just one line for all the common account_id present in the table with the following condition:
For an account_id with several id_intern:
consider those lines with the status active 'yes',
then those lines with entered mobile_no (not empty),
then those lines with entered landline_no (not empty),
then those lines with entered email (not empty),
then if still we have several lines (in this case for users with name A and B)
then we will consider the line with max id_intern.
Expected Result :
id account_id id_intern Name active mobile_no landline_no email
2 0011abs 66655 B yes 098937666 098937666 b#gmail.com
I tried the script but i am unable to fulfil these conditions :(
Thanks in advance for your help.
Use row_number() window function:
select id, account_id, id_intern, Name, Active, mobile_no, landline_no, email
from (
select *, row_number() over (partition by account_id order by id_intern desc) rn
from tablename
where Active = 'yes'
and mobile_no is not null and landline_no is not null and email is not null
) t
where rn = 1
If you want 1 row for each account_id even if not all the conditions are satisfied, the you must use a conditional ORDER BY clause:
select id, account_id, id_intern, Name, Active, mobile_no, landline_no, email
from (
select *,
row_number() over (
partition by account_id
order by
case when Active = 'yes' then 1 else 2 end,
case when mobile_no is not null then 1 else 2 end,
case when landline_no is not null then 1 else 2 end,
case when email is not null then 1 else 2 end,
id_intern desc
) rn
from tablename
) t
where rn = 1

Updating Rows in a normalized table

normalized table
ID SEQ Type Value Flag
1 1 a 100 -
1 2 a 200 -
1 3 a 250 -
1 4 b 200 -
2 1 a 150 -
2 2 b 100 -
2 3 b 200 -
How do I write a single update statement such that the resulting table is populated as follows
ID SEQ Type Value Flag
1 1 a 100 valid
1 2 a 200 repeat
1 3 a 250 repeat
1 4 b 200 valid
2 1 a 150 valid
2 2 b 100 valid
2 3 b 200 repeat
Edit: included seq column
only the first occurence of the value for a type for a ID group should have the valid flag
should it be written as two separate update statements?
can someone clarify me?
Much appreciated
Populate the table first using row_number() and then update the table.
Option 1:
select
Id,
Type,
Value,
null as Flag,
row_number() over (partition by ID, Type order by SEQ) as rnk
from yourTable
then you can use update
update yourTable
set flag = case
when rnk = 1 then 'valid'
else 'repeat'
end
Option 2:
You may be able to do without using update statement as following
select
Id,
SEQ,
Type,
Value,
case
when rnk = 1 then 'valid'
else 'repeat'
end as flag
from
(
select
Id,
SEQ,
Type,
Value,
row_number() over (partition by ID, Type order by SEQ) as rnk
from yourTable
) val

SQL find total count of each type in a column

I'm learning SQL and am stumped on what should be a simple query. I have a table with the following pattern:
Id | Type
------------
1 | Red
2 | Blue
3 | Blue
4 | Red
..
I would like to write a query to return a table that counts the total number of instances of each type and returns a table with the following pattern, for example, if 'Blue' occurs in 12 rows, and 'Red' occurs in 16 rows in the table above, the result would be:
Blue | Red
-----------
12 | 16
You could do it this way:
SELECT Type, COUNT(*) FROM TABLE GROUP BY Type
If you'd like to see the Types in separate columns, you could do this:
SELECT SUM(CASE WHEN Type = 'Blue' THEN 1 ELSE 0 END) AS Blue, SUM(CASE WHEN Type = 'Red' THEN 1 ELSE 0 END) AS Red FROM TABLE
I suggest using count over partition by. Here's a code I wrote to help my company check for duplicate Technician EmployeeID's and Pincodes, including count and YES/NO columns to allow filtering in excel so they can see what corrections need to be made:
select
t.TechnicianId, t.TechnicianName, t.Pincode, t.EmployeeID
, [Pincode Count] = count(t.Pincode) over (partition by t.Pincode)
, [Duplicate Pincode?] = case count(t.Pincode) over (partition by t.Pincode) when 1 then 'NO' else 'YES' end
, [EmployeeID Count] = count(t.EmployeeID) over (partition by t.EmployeeID)
, [Duplicate EmployeeID?] = case count(t.EmployeeID) over (partition by t.EmployeeID) when 1 then 'NO' else 'YES' end
from Technicians t
group by t.TechnicianId, t.TechnicianName, t.Pincode, t.EmployeeID
order by 4

GROUP result set BY column provided an element in group has different column with specific value

If I had a table as shown below and I want to find the max date for each ID, provided at least one of the elements of the ID group has an Info value of 1. So ID 2 would not be included since both of the elements with ID of 2 have an Info value of 2. ID 1 and 3 are included because those ID fields do have at least 1 element with Info value of 1.
ID Date Info
---------------------------
1 01-01-2013 1
1 02-02-2013 2
1 03-03-2013 2
2 01-01-2013 2
2 04-04-2013 2
3 01-01-2013 3
3 05-05-2013 1
3 06-06-2013 1
So output would look like this.
ID MaxDate
-----------------
1 03-03-2013
3 06-06-2013
Thank you very much for your help.
You can use the EXISTS predicate to check that a record where info = 1 exists for the given ID
SELECT T.ID, MaxDate = MAX(T.Date)
FROM T
WHERE EXISTS
( SELECT 1
FROM T T2
WHERE T2.ID = T.ID
AND T2.Info = 1
)
GROUP BY T.ID;
You can achieve the same thing with a conditional aggregate in the HAVING clause:
SELECT T.ID, MaxDate = MAX(T.Date)
FROM T
GROUP BY T.ID
HAVING COUNT(CASE WHEN T.Info = 1 THEN 1 END) > 0;
does this work for you?
Select id, max(date)
From my_table
where id in (select id from my_table where info = 1)
group by id