how to fetch rows in sql server based on values of column - sql

id dept Person Rating
-------------------------------------------
1 ece p1 R1
2 ece p2 t1
3 eee P3 R2
4 eee p4 M
5 Civil P5 R2
6 Civil P6 t2
7 Civil P7 t2
8 Mech p8 R2
9 Mech P9 NULL
10 IT P10 R2J
11 IT P11 T2
12 IT P12 T2
I would like to fetch all the rows whose department's rating has at least one value like 'P%' and one like 'T%'.

A rather direct method uses exists:
select t.*
from t
where exists (select 1 from t t2 where t2.dept = t.dept and t2.rating like 'P%') and
exists (select 1 from t t2 where t2.dept = t.dept and t2.rating like 'T%') ;

Related

SQL Server : multiple rows single line

I would like to get the representation of one record based on the primary key value from multiple tables. As shown below, each table can have multiple values based on this primary key value.
TABLE-1
ID
NAME
1
AA
2
BB
3
CC
4
DD
5
EE
TABLE-2
ID
SCHOOL
AUT
1
11
A
2
11
A
2
12
B
3
11
A
4
12
A
4
13
B
5
13
A
TABLE-3
ID
TC
1
101
2
102
2
103
2
104
3
105
4
106
4
107
5
108
The result below is the value obtained with an OUTER JOIN.
SELECT
T1.ID, T2.SCHOOL, T3.TC, T2.AUT
FROM
T1
LEFT OUTER JOIN
T2 ON T1.ID = T2.ID
LEFT OUTER JOIN
T3 ON T1.ID = T3.ID
ORDER BY
T1.ID ASC
ID
SCHOOL
TC
AUT
1
11
101
A
2
11
102
A
2
12
102
B
2
11
103
A
2
12
103
B
2
11
104
A
2
12
104
B
3
11
105
A
4
12
106
A
4
13
106
B
4
12
107
A
4
13
107
B
5
13
106
A
How can I get the result like below?
ID
SCHOOL
TC1
TC2
TC3
1
11
101
2
11
102
103
104
3
11
105
4
12
106
107
5
13
108
The important thing here is that in the result value, SCHOOL only shows that AUT is 'A'.
I would appreciate it if you let me know your query.
It looks, from your desired results, you just need to use row_number in combination with a conditional aggregate. Your sample data seems a little inadequate, I can't see any requirement for table1 at all.
Try the following:
with t as (
select t2.id,t2.school,t3.tc, Row_Number() over(partition by t2.id order by t3.tc) col
from t2 join t3 on t2.id=t3.id
where aut='A'
)
select id,school,
max(case when col=1 then tc end) TC1,
max(case when col=2 then tc end) TC2,
max(case when col=3 then tc end) TC3
from t
group by id, school
Example SQL Fiddle
SELECT
T1.ID, T2.SCHOOL,
GROUP_CONCAT(T3.TC),
GROUP_CONCAT(T2.AUT)
FROM
T1
LEFT OUTER JOIN
T2 ON T1.ID = T2.ID
LEFT OUTER JOIN
T3 ON T1.ID = T3.ID
GROUP BY
T1.ID, T2.SCHOOL
WHERE
T2.AUT = ‘A’
ORDER BY
T1.ID ASC
Notice that GROUP_CONCAT concatenates the values in the row.
EDIT: oh my, haven't seen that it's a SQL Server question!
Just replace GROUP_CONCAT with STRING_AGG if you’re using SQL Server 2017 or newer.

SQL - join tables on multiple columns

I want to join few tables:
table1:
A B_key B_version C D
123 abc 1 ccc 11
123 abc 2 ddd 11
456 dfg 1 rrr 22
789 vvv 1 55
table2:
A E F
123 s 5
456 r
111 t 2
table3:
B_key B_version G
abc 1 aa
abc 1 bb
abc 2 aa
abc 2 cc
dfg 1 aa
so the result would look like this:
A B_key B_version C D E F G
123 abc 1 ccc 11 s 5 aa
123 abc 1 ccc 11 s 5 bb
123 abc 2 ddd 11 s 5 aa
123 abc 2 ddd 11 s 5 cc
456 dfg 1 rrr 22 r aa
789 vvv 1 55
Version can go as high as 8.
IF I don't have A, B_key or B_version - the line is useless. Otherwise I need to keep all the information I do have.
In reality I have many more columns.
I've tried:
SELECT table1.A, table 1.B_key, table 1.B_version, table 1.C, table 1.D,
table2.E, table2.F,
table3.G
FROM table1
LEFT JOIN table2
ON table1.A = table2.A
LEFT JOIN table3
ON table1.B_key = table3.B_key AND
table1.B_version = table3.B_version
and the same with FULL JOIN.
It ends up the same: for every B_key only the highest B_version is kept, while the others disappear.
How can I avoid loosing information?
You can use left joins among tables as below :
select t1.A, t1.B_key, t1.B_version, t1.C, t1.D, t2.E, t2.F, t3.G
from table1 t1
left join table2 t2 on t2.A = t1.A
left join table3 t3 on t3.B_key = t1.B_key and t3.B_version = t1.B_version
Demo
in order to bring also the rows for unmatched values for join conditions.
If I understand correctly, you want all the b_keys and b_versions from table1 and table3. Then you want to bring in the other data. That suggests left joins
select . . .
from ((select B_key, B_version
from table1
) union -- on purpose to remove duplicates
( select B_key, B_version
from table3
)
) bb left join
table1 t1
on t1.b_key = bb.b_key and
t1.b_version = bb.b_version left join
table2 t2
on t2.a = t1.a left join
table3 t3
on t1.b_key = bb.b_key and
t1.b_version = bb.b_version;

split 1 record into 4 records(transpose row into column) in oracle

I have one record in table and i want to split this record into 4 records based on condition(if is Multirecord=1) and Q has null so no new record needed.(if Q3 is null then 3rd row not required)
and insert into new table.Details are:
Table: emp
UID name is_Multirecord Q1 P1 T1 .... Q4 P4 T4
1 xyz 1 10 $200 15-03-2019 40 $500 18-03-2019
Output in table EMp_split
record_no UID Nae is_Multi Q P T
1 1 xyz 1 10 $200 15-03-2019
2 1 xyz 1 20 $300 16-03-2019
.....
4. 1 XYZ 1 40 $500 18-03-2019
Please assist.Let me know if any other information required.
You can do the following:
SELECT UID as record_no, name as Nae, is_multirecord as is_Multi, Q1 as Q, P1 as P, T1 as T
WHERE is_multirecord = 1
UNION
SELECT UID as record_no, name as Nae, is_multirecord as is_Multi, Q2 as Q, P2 as P, T2 as T
WHERE is_multirecord = 1
UNION
SELECT UID as record_no, name as Nae, is_multirecord as is_Multi, Q3 as Q, P3 as P, T3 as T
WHERE is_multirecord = 1
UNION
SELECT UID as record_no, name as Nae, is_multirecord as is_Multi, Q4 as Q, P4 as P, T4 as T
WHERE is_multirecord = 1

Eliminate duplicate rows by outer joining two table in Oracle 11i

I have following two table with sample Data.
PLACED_PERSON_INFO
*PLACED_PERSON_INFO_GUID CPR*
P1 0201026157
P2 0309929493
P3 0002170000
P4 0000011037
P5 1201006694
P6 1201009887
P7 1110007144
P8 0309906353
P9 0101002420
PLACED_PERSON_PLACES
*PP_ID PLACEMENT_DATE PLACEMENT_STOP PLACED_PERSON_INFO_GUID*
1 01-01-2014 31-12-2014 P1
2 01-01-2014 31-12-2014 P1
3 01-01-2013 31-12-2013 P2
4 01-06-2014 30-10-2014 P3
5 01-02-2014 30-10-2014 P3
6 01-01-2013 01-01-2015 P4
7 01-01-2013 30-05-2013 P4
8 01-01-2012 30-03-2013 P5
I have written the following SQL Query to get the result combining these two tables.
SQL Query :
SELECT
PPI.PLACED_PERSON_INFO_GUID, PPI.CPR
FROM PLACED_PERSON_PLACES PPP, PLACED_PERSON_INFO PPI
WHERE (PPP.PLACEMENT_DATE <= SYSDATE OR PPP.PLACEMENT_DATE IS NULL)
AND (PPP.PLACEMENT_STOP >= SYSDATE OR PPP.PLACEMENT_STOP IS NULL)
AND PPP.PLACED_PERSON_INFO_GUID (+) = PPI.PLACED_PERSON_INFO_GUID
ORDER BY PPI.CPR;
Query Result:
PLACED_PERSON_INFO_GUID CPR
P1 0201026157
P1 0201026157
P3 0002170000
P3 0002170000
P4 0000011037
P6 1201009887
P7 1110007144
P8 0309906353
P9 0101002420
But I want the following result where duplicate rows will not be shown. I do not want to use DISTINCT keyword. Can anyone help me in this result? I am using Oracle 11i.
Expected Result:
PLACED_PERSON_INFO_GUID CPR
P1 0201026157
P3 0002170000
P4 0000011037
P6 1201009887
P7 1110007144
P8 0309906353
P9 0101002420
First, you should write your query using explicit join syntax:
SELECT PPI.PLACED_PERSON_INFO_GUID, PPI.CPR
FROM PLACED_PERSON_INFO PPI LEFT JOIN
PLACED_PERSON_PLACES PPP
ON PPP.PLACEMENT_DATE <= SYSDATE AND
PPP.PLACEMENT_STOP >= SYSDATE AND
PPP.PLACED_PERSON_INFO_GUID = PPI.PLACED_PERSON_INFO_GUID
ORDER BY PPI.CPR;
If you only want one row, then you can use row_number():
SELECT PLACED_PERSON_INFO_GUID, CPR
FROM (SELECT PPI.PLACED_PERSON_INFO_GUID, PPI.CPR,
ROW_NUMBER() OVER (PARTITION BY PPI.PLACED_PERSON_INFO_GUID, PPI.CPR ORDER BY PPI.CPR) as seqnum
FROM PLACED_PERSON_INFO PPI LEFT JOIN
PLACED_PERSON_PLACES PPP
ON PPP.PLACEMENT_DATE <= SYSDATE AND
PPP.PLACEMENT_STOP >= SYSDATE AND
PPP.PLACED_PERSON_INFO_GUID = PPI.PLACED_PERSON_INFO_GUID
) p
WHERE seqnum = 1;
ORDER BY CPR;
You can add additional columns and still only get one row per pair.
Solution is :
SELECT PLACED_PERSON_INFO_GUID, CPR
FROM (SELECT PPI.PLACED_PERSON_INFO_GUID, PPI.CPR,
ROW_NUMBER() OVER (PARTITION BY PPI.PLACED_PERSON_INFO_GUID, PPI.CPR ORDER BY PPI.CPR) AS SEQNUM
FROM PLACED_PERSON_INFO PPI LEFT JOIN PLACED_PERSON_PLACES PPP
ON PPP.PLACED_PERSON_INFO_GUID = PPI.PLACED_PERSON_INFO_GUID
WHERE (PPP.PLACEMENT_DATE <= SYSDATE OR PPP.PLACEMENT_DATE IS NULL)
AND (PPP.PLACEMENT_STOP >= SYSDATE OR PPP.PLACEMENT_STOP IS NULL)
) P
WHERE SEQNUM = 1
ORDER BY CPR

How to insert new data while keeping most columns value but changing some values dynamically?

I am using Sql Server 2005. I have this tableA with 70 columns and about 5000rows. I would like to create new data(around 200 new records) for simulation purposes. Out of the 70 columns, i only want to change values of 3 columns (TERMID, OUTLET, SNUM) the rest remains. E.g
TABLEA
SNO COMPANY.......TERMID........OUTLET........SNUM.....
1 ABC PP2 P1-P5 P5
1 ABC PP2 P1-P5 P4
2 ABC PP2 P1-P5 P4
1 ABC PP2 P1-P5 P3
3 ABC PP2 P1-P5 P3
so i would like to keep all values for the new records except changing all TERMID from PP2 to PP3 and all outlet from P1-P5 to P6-P8. As for SNUM all P5 will become P8, P4 will become P7 and P3 will become P6. Meaning TABLEA will look like this after i do the insert:
TABLEA
SNO COMPANY.......TERMID........OUTLET........SNUM.....
1 ABC PP2 P1-P5 P5
1 ABC PP2 P1-P5 P4
2 ABC PP2 P1-P5 P4
1 ABC PP2 P1-P5 P3
3 ABC PP2 P1-P5 P3
1 ABC PP3 P6-P8 P8
1 ABC PP3 P6-P8 P7
2 ABC PP3 P6-P8 P7
1 ABC PP3 P6-P8 P6
3 ABC PP3 P6-P8 P6
I do not want to do this manually as it will be very tedious for 200 rows. Is this possible using SQL statements?
I have tot of writing normal insert statements with subquery but i guess it will be as tedious or maybe even more to write INSERT INTO TABLEA ( COL1, COL2,.......COL70) VALUE (.....)
Any smart idea?
I just reread your response, and realize you're trying to Insert records in your current table, not create a new table.
How about:
SELECT *
INTO #NewTable
FROM TABLEA;
UPDATE #NewTable
SET TERMID = 'PP3',
OUTLET= 'P6-P8',
SNUM = CASE
WHEN SNUM = 'P5' THEN 'P8'
WHEN SNUM = 'P4' THEN 'P7'
WHEN SNUM = 'P3' THEN 'P6'
END;
INSERT INTO TABLEA
SELECT *
FROM #NewTable
Sorry for the confusion.