How do I create multiple rows in a new table based on a common value in another table?
ProviderTable: PersonTable:
-------------------- ---------------------
ProviderID | GroupID PersonID | ProviderID
1 | A 100 | 1
2 | A 101 | 3
3 | A 102 | 8
4 | NULL 103 | 10
5 | B 104 | 5
6 | C 105 | 4
7 | B
8 | NULL
9 | NULL
10 | C
ProviderTable.ProviderID = PersonTable.ProviderID
I need to create a new table with a person row for each provider where Provider.GroupID=Provider.GroupID
Results I am looking for:
New-table:
PersonID | ProviderID
100 | 1
100 | 2
100 | 3
101 | 3
101 | 1
101 | 2
102 | 8
103 | 10
103 | 6
104 | 5
104 | 7
105 | 4
This quick version gets the sort order you are looking for. Test data is included:
DECLARE #pt table (
ProviderId int,
GroupId varchar(2)
)
DECLARE #pet table (
PersonId int,
ProviderId int
)
INSERT INTO #pt Values
(1,'A'),
(2,'A'),
(3,'A'),
(4,NULL),
(5,'B'),
(6,'C'),
(7,'B'),
(8,NULL),
(9,NULL),
(10,'C')
INSERT INTO #pet VALUES
(100,1),
(101,3),
(102,8),
(103,10),
(104,5),
(105,4)
SELECT pe.PersonId,
IsNull(p2.ProviderId, p1.providerId) As ProviderId
FROM #pt p1
INNER JOIN #pet pe
ON p1.ProviderId = pe.ProviderId
LEFT JOIN #pt p2
ON p1.GroupId = p2.GroupId
ORDER BY pe.personId,
CASE
WHEN pe.ProviderId = p2.ProviderId
Then 0
ELSE 1
END
You can use the following SQL-statement:
SELECT PER.PersonID, COALESCE(PG.ProviderID, PP.ProviderID) AS ProviederID
FROM PersonTable PER
INNER JOIN ProviderTable PP
ON PP.ProviderID = PER.ProviderID
LEFT OUTER JOIN ProviderTable PG
ON PG.GroupID = PP.GroupID;
Related
I want to update one table using another table on field "Id" such that it wont create duplicates
let say my first table is Table1 and second table is Table2 . I would like to update the row in Table1 from Table2 when the Id is matching
I am aware of using UNION function but this applies to entire columns where I only need to consider a single column.
https://docs.snowflake.com/en/sql-reference/operators-query.html#union-all
Example of my Tables
Table1
Id name number value
1 a 8 100
2 b 8 100
3 c 8 100
4 d 8 100
Table2
Id name number value
3 c 8 99
4 d 6 100
5 e 7 100
Expected output
Id name number value
1 a 8 100
2 b 8 100
3 c 8 99
4 d 6 100
5 e 7 100
Please note that in the output table row with Id 3,4 has be updated and new Id 5 is inserted. Can someone help me with the select query to get the desired output?
You can use MERGE command:
merge into table1 using table2 on table1.id = table2.id
when matched then
update set table1.name = table2.name, table1.number = table2.number, table1.value = table2.value
when not matched then
insert (Id,name,number,value) values (table2.id, table2.name, table2.number, table2.value);
select * from table1;
+----+------+--------+-------+
| ID | NAME | NUMBER | VALUE |
+----+------+--------+-------+
| 5 | e | 7 | 100 |
| 1 | a | 8 | 100 |
| 2 | b | 8 | 100 |
| 3 | c | 8 | 99 |
| 4 | d | 6 | 100 |
+----+------+--------+-------+
https://docs.snowflake.com/en/sql-reference/sql/merge.html
If you don't want to update the table, you may use IFNULL and full outer join:
select
IFNULL( t1.id, t2.id) id,
IFNULL( t2.name, t1.name ) name,
IFNULL( t2.number, t1.number ) number,
IFNULL( t2.value, t1.value ) value
from table1 t1
full join table2 t2
on t1.id = t2.id;
+----+------+--------+-------+
| ID | NAME | NUMBER | VALUE |
+----+------+--------+-------+
| 1 | a | 8 | 100 |
| 2 | b | 8 | 100 |
| 3 | c | 8 | 99 |
| 4 | d | 6 | 100 |
| 5 | e | 7 | 100 |
+----+------+--------+-------+
I have a table with a million records. I need to update some columns which are null based on the existing 'not null' records of a particular id based columns. I've tried with one query, it seems to be working fine but I don't have confidence in it that it will be able to update all those 1 million records exactly the way I need. I'm providing you some sample data how my table looks like.Any help will be appreciated
SELECT * INTO #TEST FROM (
SELECT 1 AS EMP_ID,10 AS DEPT_ID,15 AS ITEM_NBR ,NULL AS AMOUNT,NULL AS ITEM_NME
UNION ALL
SELECT 1,20,16,500,'ABCD'
UNION ALL
SELECT 1,30,17,NULL,NULL
UNION ALL
SELECT 2,10,15,1000,'XYZ'
UNION ALL
SELECT 2,30,16,NULL,NULL
UNION ALL
SELECT 2,40,17,NULL,NULL
) AS A
Sample data:
+--------+---------+----------+--------+----------+
| EMP_ID | DEPT_ID | ITEM_NBR | AMOUNT | ITEM_NME |
+--------+---------+----------+--------+----------+
| 1 | 10 | 15 | NULL | NULL |
| 1 | 20 | 16 | 500 | ABCD |
| 1 | 30 | 17 | NULL | NULL |
| 2 | 10 | 15 | 1000 | XYZ |
| 2 | 30 | 16 | NULL | NULL |
| 2 | 40 | 17 | NULL | NULL |
+--------+---------+----------+--------+----------+
Expected result:
+--------+---------+----------+--------+----------+
| EMP_ID | DEPT_ID | ITEM_NBR | AMOUNT | ITEM_NME |
+--------+---------+----------+--------+----------+
| 1 | 10 | 15 | 500 | ABCD |
| 1 | 20 | 16 | 500 | ABCD |
| 1 | 30 | 17 | 500 | ABCD |
| 2 | 10 | 15 | 1000 | XYZ |
| 2 | 30 | 16 | 1000 | XYZ |
| 2 | 40 | 17 | 1000 | XYZ |
+--------+---------+----------+--------+----------+
I tried this but I'm unable to conclude whether it is updating all the 1 million records properly.
SELECT * FROM #TEST T
inner JOIN #TEST T1 ON T1.EMP_ID=T.EMP_ID
WHERE T1.AMOUNT IS NOT NULL
UPDATE T SET AMOUNT=T1.AMOUNT
FROM #TEST T
inner JOIN #TEST T1 ON T1.EMP_ID=T.EMP_ID
WHERE T1.AMOUNT IS not NULL
I have used UPDATE using inner join
UPDATE T
SET T.AMOUNT = X.AMT,T.ITEM_NME=X.I_N
FROM #TEST T
JOIN
(SELECT EMP_ID,MAX(AMOUNT) AS AMT,MAX(ITEM_NME) AS I_N
FROM #TEST
GROUP BY EMP_ID) X ON X.EMP_ID = T.EMP_ID
SELECT * into #Test1
FROM #TEST
WHERE AMOUNT IS NOT NULL
For records validation run this query first
SELECT T.AMOUNT, T1.AMOUNT, T1.EMP_ID,T1.EMP_ID
FROM #TEST T
inner JOIN #TEST1 T1 ON T1.EMP_ID=T.EMP_ID
WHERE T.AMOUNT IS NULL
Begin Trans
UPDATE T
SET T.AMOUNT=T1.AMOUNT, T.ITEM_NME= = T1.ITEM_NME
FROM #TEST T
inner JOIN #TEST1 T1 ON T1.EMP_ID=T.EMP_ID
WHERE T.AMOUNT IS NULL
rollback
SELECT EMP_ID,MAX(AMOUNT) as AMOUNT MAX(ITEM_NAME) as ITEM_NAME
INTO #t
FROM #TEST
GROUP BY EMP_ID
UPDATE t SET t.AMOUNT = t1.AMOUNT, t.ITEM_NAME = t1.ITEM_NAME
FROM #TEST t INNER JOIN #t t1
ON t.emp_id = t1.emp_id
WHERE t.AMOUNT IS NULL and t.ITEM_NAME IS NULL
Use MAX aggregate function to get amount and item name for each employee and then replace null values of amount and item name with those values. For validation use COUNT function to calculate the number of rows with values of amount and item name as null. If the number of rows is zero then table is updated correctly
I have a question about SQL Server.
Table patient:
pn | code | date | doctorcode
---------------------------------------
1 | 10 |2015-02-19 | 100
1 | 10 |2015-02-19 | 101
1 | 10 |2015-02-19 | 102
2 | 10 |2015-02-12 | 101
2 | 10 |2015-02-13 | 102
2 | 10 |2015-02-14 | 103
3 | 10 |2015-02-15 | 103
3 | 10 |2015-02-18 | 104
3 | 10 |2015-02-26 | 105
Table Patientref:
pn | code | sdate | edate | Status
-------------------------------------------------
1 | 10 |2015-02-13 | 2015-02-19 | 1
1 | 10 |2015-02-19 | 2015-03-24 | 2
1 | 10 |2015-04-28 | 2015-05-08 | 4
2 | 10 |2015-02-08 | 2015-02-19 | 4
2 | 10 |2015-02-09 | 2015-02-19 | 2
2 | 10 |2015-02-10 | 2015-02-19 | 2
2 | 10 |2015-02-11 | 2015-02-18 | 1
3 | 10 |2015-02-10 | 2015-02-17 | 4
3 | 10 |2015-02-10 | 2015-02-17 | 3
3 | 10 |2015-02-11 | 2015-02-18 | 3
2 | 10 |2015-04-10 | 2015-05-19 | 2
3 | 10 |2015-02-11 | 2015-02-18 | 1
3 | 10 |2015-02-26 | 2015-03-18 | 1
Here we need consider patient dates that fall between sdate and edate of the patientrefs table, and then we need to consider the highest status values in order (for example, the highest values in order - 2 is first highest, 4 is second highest, 3 is third highest, and 1 is fourth highest value)
If the date falls between multiple different sdate and edate with the same status values, then we need to consider the latest sdate value and from that entire record we need to extract that value.
Examples: patient
pn | code | date | doctorcode
2 | 10 |2015-02-12 | 101
2 | 10 |2015-02-13 | 102
2 | 10 |2015-02-14 | 103
Table : Patientref:
pn | code | sdate | edate | Status
2 | 10 |2015-02-08 | 2015-02-19 | 4
2 | 10 |2015-02-09 | 2015-02-19 | 2
2 | 10 |2015-02-10 | 2015-02-19 | 2
2 | 10 |2015-02-11 | 2015-02-18 | 1
Here, pn=2 values have dates which fall between sdate and edate of patientref table. Then we give highest values status is 2, and status 2 values have two records, then we go for max sdate(latest sdate). Then this pn=2 latest sdates is 2015-02-10 and we need to retrieve the corresponding edate and status values.
Based on this, the desired output is below:
pn | code | date | doctorcode | sdate |edate |status
1 | 10 |2015-02-19 | 100 |2015-02-19 |2015-03-24 | 2
1 | 10 |2015-02-19 | 101 |2015-02-19 |2015-03-24 | 2
1 | 10 |2015-02-19 | 102 |2015-02-19 |2015-03-24 | 2
2 | 10 |2015-02-12 | 101 |2015-02-10 |2015-02-19 | 2
2 | 10 |2015-02-13 | 102 |2015-02-10 |2015-02-19 | 2
2 | 10 |2015-02-14 | 103 |2015-02-10 |2015-02-19 | 2
3 | 10 |2015-02-15 | 103 |2015-02-10 |2015-02-17 | 4
3 | 10 |2015-02-18 | 104 |2015-02-11 |2015-02-18 | 3
3 | 10 |2015-02-26 | 105 |2015-02-26 |2015-03-18 | 1
I tried it like this:
select
a.pn, a.code, a.doctorcode, a.date,
b.sdate, b.edate, b.status
from
patient a
left join
(select
b.pn, b.code, b.sdate, b.edate,
row_number() over (partition by pn, org
order by case when status=2 then 1 when status=4 then 2 when status=3 then 3 when status=1 then 4 end desc,sdate desc) as rn
from patientref) b on a.pn = b.pn and a.code = b.code
and a.rn = 1
and a.date between b.sdate and b.edate
But it does not give the expected result. How can I write the query to achieve this task in SQL Server?
First off, to handle the status sorting you should really have a table in your system showing how they can be sorted. This would just be a table that has the status ID and a sort order column showing sorting priority. However, for your query you can just create a table variable to manage it.
declare #statuses table
([status] int,
sort_order int)
insert into #statuses ([status], sort_order) values (2,0);
insert into #statuses ([status], sort_order) values (4,1);
insert into #statuses ([status], sort_order) values (3,2);
insert into #statuses ([status], sort_order) values (1,3);
Then you can use CROSS APPLY to query your patient table and use the highest priority record from your patientref table:
select
p.pn,
p.code,
p.date,
p.doctorcode,
ca.sdate,
ca.edate,
ca.status
from patient p
cross apply
(select
top 1
pr.pn,
pr.code,
pr.sdate,
pr.edate,
pr.status
from patientref pr
inner join #statuses s on pr.status = s.status
where pr.pn = p.pn
and pr.code = p.code
and p.date between pr.sdate and pr.edate
order by s.sort_order, pr.sdate desc) as ca
I have question about SQL Server
Source: emp
id | name | check |deptname
100 | a | 1 |ceo
100 | b | 2 |hr
100 | c | 3 |po
100 | d | 5 |no
101 | a | 1 |pm
101 | b | 5 |ceo
102 | a | 1 |rn
102 | b | 2 |han
Here same id have check 2 and 5 values then we need to replace check values to 2 check values for that id.
Based on above table I want load/output data into target table like below
Target : emp1
id | name | check |deptname
100 | a | 1 |ceo
100 | d | 2 |hr
100 | c | 3 |po
101 | a | 1 |pm
101 | b | 5 |ceo
102 | a | 1 |rn
102 | b | 2 |han
and I tried like below
select
a1.id,
a1.name,
isnull(a2.[check],a1.[check]) as [check]
from
emp as a1
left outer join
emp as a2 on a2.id = a1.id
and a1.[check] in (2,5)
and a2.[check] in (2,5)
and a2.[check] <> a1.[check]
where
a2.id is null
or (a1.[check] = 5
and a2.[check] = 2)
That query does not return the right result.
Please tell me how to write query to get the expected output in SQL Server
This is how you can do that:
select
e1.id,
isnull(e2.name, e1.name) as name,
e1.[check],
e1.deptname
from emp e1
left outer join emp e2
on e2.id = e1.id and e1.[check] = 2 and e2.[check] = 5
where
not exists (select 1 from emp e3 where e3.id = e1.id and
e1.[check] = 5 and e3.[check] = 2)
Example in SQL Fiddle
I am using sqlserver and I have two table which contains below data. I need to select those matched rows without duplicate.
Table_A:
A_ID | Item_ID
--------------------
1 | 101
2 | 101
3 | 103
4 | 103
5 | 199
Table_B:
B_ID | Item_ID
--------------------
11 | 101
12 | 101
13 | 102
14 | 103
15 | 103
16 | 103
Expected Result:
A_ID | Item_ID | B_ID
----------------------
1 | 101 | 11
2 | 101 | 12
3 | 103 | 14
4 | 103 | 15
I tried:
SELECT A_ID, a.Item_ID, B_ID FROM Table_A a LEFT JOIN
Table_B b ON a.Item_ID = b.Item_ID
But it show all the possible records.
How can i display the expected result above?
Based on the result set you gave you want one unique record from B for each A, ignoring records in A for which there is no corresponding record in B. The following will work:
SELECT
AValues.A_ID,
AValues.Item_ID,
BValues.B_ID
FROM
(SELECT
A_ID,
Item_ID,
ROW_NUMBER() OVER(PARTITION BY Item_ID ORDER BY A_ID) ARowID
FROM
Table_A) AValues
INNER JOIN (SELECT
B_ID,
Item_ID,
ROW_NUMBER() OVER(PARTITION BY Item_ID ORDER BY B_ID) BRowID
FROM
Table_B) BValues ON AValues.Item_ID = BValues.Item_ID AND AValues.ARowID = BValues.BRowID