Please help me. I need to replace table1's code1,code2,code3 values to table2 description.
Table 1
ID CODE1 CODE2 CODE3
--------------------------
222 4wta 5qer 2qrst
223 5qer 4rstu 4tws
224 4tws 2thua 1thur
225 4tws 5qer 3wrst
Table 2
code description
-------------------
4wta Good
5qer medium
2qrst Average
1thur Mild
3wrst Progress
2thua Success
4rstu Poor
4tws Low
After Replace
ID CODE1 CODE2 CODE3
-----------------------------
222 Good medium Average
You can join table2 to table1 for each column (this will require 3 joins):
SELECT t1.id,
t2a.description AS code1,
t2b.description AS code2,
t2c.description AS code3
FROM table1 t1
INNER JOIN table2 t2a ON t1.code1 = t2a.code
INNER JOIN table2 t2b ON t1.code2 = t2b.code
INNER JOIN table2 t2c ON t1.code3 = t2c.code
Or you could unpivot table1 from columns to rows then perform a single join to table2 and then pivot the table back from rows to columns:
WITH pivoted_values ( id, name, description ) AS (
SELECT id,
name,
t2.description
FROM (
SELECT *
FROM table1
UNPIVOT ( code FOR name IN ( code1, code2, code3 ) )
) t1
INNER JOIN table2 t2 ON t1.code = t2.code
)
SELECT id,
code1,
code2,
code3
FROM pivoted_values
PIVOT (
MAX( description )
FOR name IN (
'CODE1' AS code1,
'CODE2' AS code2,
'CODE3' AS code3
)
)
Both of them output:
ID | CODE1 | CODE2 | CODE3
--: | :----- | :------ | :-------
222 | Good | medium | Average
223 | medium | Poor | Low
224 | Low | Success | Mild
225 | Low | medium | Progress
db<>fiddle here
Related
I am looking to join 3 tables, all with the same data except one column is a different name (different date for each of the the 3 tables). The three tables look like the following. The goal is if a condition exists in table 1 AND/OR table 2 determine if a condition does or does not exist in table 3 for each individual id/condition. I'm currently left joining table 2 to table 1 but I'm aware that is not accounting for if a condition in table 2 exists that is not in table it is not being accounted for, anyways, any help would into this would be useful.
Table 1
id place Condition_2018
123 ABC flu
456 ABC heart attack
Table 2
id place Condition_2019
123 ABC flu
789 def copd
Table 3
id place Condition_2020
456 ABC heart attack
789 def copd
123 ABC flu
OUTPUT:
Table 2
id place Condition_2018 Condition_2019 Condition_2020
123 ABC flu flu flu
456 ABC heart attack null heart attack
789 def NULL copd copd
Thank you!
How about this (SQL Server syntax)...
SELECT
x.id
, x.place
, x.Condition_2018
, x.Condition_2019
, t3.Condition_2020
FROM (
SELECT
COALESCE(t1.id, t2.id) AS id
, COALESCE(t1.place, t2.place) AS place
, t1.Condition_2018
, t2.Condition_2019
FROM Table1 AS t1
FULL OUTER JOIN Table2 AS t2 ON t1.id = t2.id AND t1.place = t2.place
) AS x LEFT JOIN Table3 AS t3 ON x.id = t3.id AND x.place = t3.place
If your database supports full join, you can just do:
select
id,
place,
t1.condition_2018,
t2.condition_2019,
t3.condition_2020
from table1 t1
full join table2 t2 using(id, place)
full join table3 t3 using(id, place)
Otherwise, it is a bit more complicated: union all and aggregation is one method:
select
id,
place,
max(condition_2018) condition_2018,
max(condition_2019) condition_2019,
max(condition_2020) condition_2020
from (
select id, place, condition_2018, null condition_2019, null condition 2020 from table1
union all
select id, place, null, condition_2019, null from table2
select id, place, null, null, condition_2020 from table3
) t
group by id, place
You seem to want everything in Table3 and matches in the other two tables. That is just left joins:
select t3.id, t3.place,
t1.condition_2018, t2.condition_2019,
t3.condition_2020
from table3 t3 left join
table2 t2
on t3.id = t2.id and t3.place = t2.place left join
table1 t1
on t3.id = t1.id and t3.place = t1.place;
You need a full outer join of table1 and table2 and a left join to table3:
select
coalesce(t1.id, t2.id) id,
coalesce(t1.place, t2.place) place,
t1.Condition_2018,
t2.Condition_2019,
t3.Condition_2020
from table1 t1 full outer join table2 t2
on t2.id = t1.id
left join table3 t3
on t3.id = coalesce(t1.id, t2.id)
See the demo.
Results:
> id | place | Condition_2018 | Condition_2019 | Condition_2020
> --: | :---- | :------------- | :------------- | :-------------
> 123 | ABC | flu | flu | flu
> 456 | ABC | heart attack | null | heart attack
> 789 | def | null | copd | copd
I've got the following four SQL tables:
Table 1:
-----------------------
Product | Date_Purchase
-----------------------
abc | 06-Jan-19
def | 05-Jan-18
ghi | 05-Apr-19
abc | 06-Feb-19
Table 2:
------------------------
Product | Date_Purchase
------------------------
jkl | 6-Feb-19
mno | 2-Aug-18
ghi | 9-May-19
pqr | 1-Sep-19
Table 3:
-------------------------
Product | Date_Purchase
-------------------------
ghi | 2-Aug-18
mno | 9-May-19
pqr | 2-Aug-18
abc | 06-Jan-19
Table 4:
-------------------------
Product | Date_Purchase
-------------------------
stu | 9-May-19
vwx | 05-Apr-19
ghi | 9-May-19
def | 05-Jan-18
I've got the below code which joins the tables with Union:
SELECT Product, Date_Purchase FROM Table1 UNION ALL
SELECT Product, Date_Purchase FROM Table2 UNION ALL
SELECT Product, Date_Purchase FROM Table3 UNION ALL SELECT Product, Date_Purchase FROM Table4
ORDER BY Product, Date_Purchase;
I would like to delete all the rows from the tables, no matter the table, that appear only once in all the tables.
For example jkl, stu and vwx appear only once, so I would like to delete the entire rows from the table where they appear. Does anyone have any idea how to do that?
Also how could i delete all the products that appear in the tables and have the same purchase date?
A solution for MySql with which in 1 statement you can delete from all 4 tables:
delete t1, t2, t3, t4
from (
select u.product, count(*) counter
from (
select * from table1 union all
select * from table2 union all
select * from table3 union all
select * from table4
) u
group by u.product
) t
left join table1 t1 on t1.product = t.product
left join table2 t2 on t2.product = t.product
left join table3 t3 on t3.product = t.product
left join table4 t4 on t4.product = t.product
where t.counter = 1;
See the demo.
Results:
Table1
> Product | Date_Purchase
> :------ | :------------
> abc | 06-Jan-19
> def | 05-Jan-18
> ghi | 05-Apr-19
> abc | 06-Feb-19
Table2
> Product | Date_Purchase
> :------ | :------------
> mno | 2-Aug-18
> ghi | 9-May-19
> pqr | 1-Sep-19
Table3
> Product | Date_Purchase
> :------ | :------------
> ghi | 2-Aug-18
> mno | 9-May-19
> pqr | 2-Aug-18
> abc | 06-Jan-19
Table4
> Product | Date_Purchase
> :------ | :------------
> ghi | 9-May-19
> def | 05-Jan-18
If "delete" means not returning return them in a select, then:
SELECT pd.*
FROM (SELECT pd.*, COUNT(*) OVER (PARTITION BY Product) as cnt
FROM ((SELECT Product, Date_Purchase FROM Table1
) UNION ALL
(SELECT Product, Date_Purchase FROM Table2
) UNION ALL
(SELECT Product, Date_Purchase FROM Table3
) UNION ALL
(SELECT Product, Date_Purchase FROM Table4
)
) pd
) pd
WHERE cnt = 1;
If "delete" means, delete, then you need four delete statements, each like this:
delete t
from table1 t
where not exists (select 1 from table2 where t2.product = t.product) and
not exists (select 1 from table3 where t3.product = t.product) and
not exists (select 1 from table4 where t4.product = t.product);
Actually, this delete products that are only in on table, even if they are there multiple times. It can be tweaked to only delete the singletons, if that is also necessary.
To give it a try for Scratte‘s version of only if product and Date occurs twice (unchecked because written on mobile device):
SELECT pdo.*
FROM (SELECT pd.*, COUNT(*) OVER (PARTITION BY Product) as cnt
FROM ((SELECT Product, Date_Purchase FROM Table1
) UNION ALL
(SELECT Product, Date_Purchase FROM Table2
) UNION ALL
(SELECT Product, Date_Purchase FROM Table3
) UNION ALL
(SELECT Product, Date_Purchase FROM Table4
)
) pd
) pdo
Group by pdo.Product,pdo.Date_Purchase
Having cnt=1
I have two tables Table1 and Table2. I wanted to join the two tables data based on the TIME_STAMP data field
I have tried the below query but I am not able to get the expected result
Table 1
CATEGORY_ID ID TIME_STAMP VALUE
-------------------------------------
1 444 30-Mar-17 XXX
1 444 31-Jul-18 YYY
1 444 15-Jan-19 ZZZ
Table 2
CATEGORY_ID ID TIME_STAMP VALUE
------------------------------------------
2 444 30-Mar-17 10/31/2017
2 444 30-May-18 10/25/2018
2 444 13-Jun-19 10/25/2018
Actual Result:
TIME_STAMP Table 1 VALUE Table 2 value
-------------------------------------------
30-Mar-17 XXX 10/31/2017
31-Jul-18 YYY NULL
15-Jan-19 ZZZ NULL
Query :
SELECT
T1.TIME_STAMP ,
T1.X_VALUE,
T2.X_VALUE
FROM
TABLE1 T1
LEFT OUTER JOIN TABLE2 T2 ON T1.ID = T2.ID
AND
TO_CHAR(T1.TIME_STAMP,'MM/DD/YYYY')
=TO_CHAR(T2.TIME_STAMP,'MM/DD/YYYY')
AND
T2.CATEGORY_ID=2
WHERE
T1.CATEGORY_ID =1 AND T1.ID= 444
Expected Result:
TIME_STAMP Table1 VALUE Table2 VALUE
-----------------------------------------
30-Mar-17 XXX 10/31/2017
30-May-18 NULL 10/25/2018
31-Jul-18 YYY NULL
15-Jan-19 ZZZ NULL
13-Jun-19 NULL 10/25/2018
FULL OUTER JOIN with filtering is tricky. I recommend using a subquery for the filtering criteria:
select coalesce(t1.time_stamp, t2.time_stamp) as time_stamp,
t1.x_value, t2.x_value
from (select t1.*
from table1 t1
where t1.CATEGORY_ID = 1 and T1.ID = 444
) t1 full join
(select t2.*
from table2 t2
where t2.id = 444 and t2.category_id = 2
) t2
on t2.id = t1.id and
trunc(t2.time_stamp) = trunc(t1.time_stamp);
Based on your expected result I think you want to do a FULL OUTER JOIN on the TIME_STAMP column.
You could do something like this.
SELECT COALESCE(t1.time_stamp, t2.time_stamp) AS TIME_STAMP,
t1.value as T1_value,
t2.value as T2_value
FROM table01 t1
FULL OUTER JOIN table02 t2 ON t1.time_stamp = t2.time_stamp
+-------------+-----------+------------+
| TIME_STAMP | T1_value | T2_value |
+-------------+-----------+------------+
| 2017-03-30 | XXX | 10/31/2017 |
| 2018-07-31 | YYY | (null) |
| 2019-01-15 | ZZZ | (null) |
| 2018-05-30 | (null) | 10/25/2018 |
| 2019-06-13 | (null) | 10/25/2018 |
+-------------+-----------+------------+
Note: I have used SQL Server since you haven't mentioned a DBMS.
before you join the two tables with timestamp, you need trunc the timestamp to Date.
like TRUNC("TimeStamp", DATE)
SELECT COALESCE(t1.time_stamp, t2.time_stamp) AS TIME_STAMP,
t1.value as T1_value,
t2.value as T2_value
FROM table01 t1
FULL OUTER JOIN table02 t2
ON trunc(t1.time_stamp, 'DATE') = trunc(t2.time_stamp, 'DATE');
I have two tables with:
Table1:
ID_Number | Description|
a | abc
b | cde
c | fgh
Table2:
ID | Title | value
a | phone number | 555-1234
a | address | somewhere USA
a | mobile_number | 867-5309
b | phone number | ...
b | address | ...
b | mobile_number | ...
I want to create a new table with all data that belong to each ID_number that exists in Table 2.
with the query I'm able to list all.
select Table1.ID_Number, Table2.ID from Table1, Table2
where Table1_ID_number = Table2.ID))
order by ID_Number
But I would like to create a new table with:
Table3
|ID | Description| ID_data
a , abc, "Address_A_PhoneNumber_A_Mobile_Number_A"
b , cde, "Address_B_PhoneNumber_B_Mobile_Number_B"
Is this possible with SQL???
I needed to edit your question and add a third column to the second table containing values for the various types of information. Without something like this, I'm afraid your question makes no sense.
We can aggregate by ID and pivot out the address and phone numbers into a single concatenated string.
SELECT
t1.ID_Number,
t1.Description
MAX(CASE WHEN t2.title = 'address' THEN t2.value END) || '_' ||
MAX(CASE WHEN t2.title = 'phone number' THEN t2.value END) || '_' ||
MAX(CASE WHEN t2.title = 'mobile_number' THEN t2.value END) AS ID_data
FROM Table1 t1
INNER JOIN Table2 t2
ON t1.ID_Number = t2.ID
GROUP BY
t1.ID_Number,
t1.Description;
I improved my question with example tables for a better understanding
I have 3 tables with following rows:
TABLE1 t1 TABLE t2 TABLE t3
ID NAME OBS ID HW_VER ID SERIAL
----------------- ----------- ------------
1 | Name1 | Obs1 1 | HWVer1 5 | Serial5
2 | Name2 | Obs2 2 | HWVer2 6 | Serial6
3 | Name3 | Obs3 3 | HWVer3 7 | Serial7
4 | Name4 | Obs4
5 | Name5 | Obs5
6 | Name6 | Obs6
7 | Name7 | Obs7
Now, I want to select the id, name and obs when 2 conditions are fulfilled:
the id is present in t2 or t3 (never in both);
it refers to either t2 or t3 attributes (eg. t2.HW_VER='HWVER1'), never on both
I did something like this, but it's wrong:
SELECT DISTINCT t1.id, t1.name, t1.obs
FROM table1 t1, table2 t2, table3 t3
WHERE t1.id IN (t2.id, t3.id) AND t3.serial='Serial6';
I cannot use unions, external tables or views for this.
Please let me know in case of further questions.
Thanks a lot for your answers, I really appreciate your time..
You need to select from T2 OR T3 but never both? I think you want something like this
select count(*)
from t1
where exists (
select 'x'
from t2
where MyPrimaryKey_Name = 'random_name'
and t2.id = t1.id
)
or exists (
select 'x'
from t3
where MyPrimaryKey_Name = 'random_name'
and t3.id = t1.id
)