Update rows in one table depending on a column in another table - sql

I have 2 tables in different databases in SQL Server.
database1.table_A
id | name | present |
-----|------------|-----------|
1 | jon | 1 |
2 | ham | 0 |
3 | sam | 1 |
7 | tom | 1 |
database2.table_B
absentid |
----------|
1 |
5 |
7 |
For every id value present in table_B, I want the value of present in table_A to be 0. So, my final result should look like -
id | name | present |
-----|------------|-----------|
1 | jon | 0 |
2 | ham | 0 |
3 | sam | 1 |
7 | tom | 0 |
I want to confirm if the following query I wrote is correct or if there are any better ways to do this:
update database1.table_A
set present=0
FROM database1.table_A t1
inner join
database2.table_B t2
ON t1.id = t2.absentid;

If you want to set present = 1 if they are not in the table, then you would use left join:
update t1
set present = (case when t2.absentid is null then 1 else 0 end)
from database1.table_A t1 left join
database2.table_B t2
on t1.id = t2.absentid;
Otherwise, if you want to keep the value in that case, your version is fine.

Related

Select two tables side by side

I have two tables filled with two files of which table1 always has one row more than the second.
I want to merge the two tables into one. When I use a right join e.g.
select *
from table2
right join table1 on table1.id = table2.id and table1.eq_nb = table2.eq_nb
I will have the 4 combinations for eq_nb = 25 because it is repeated two times.
But I rather want to stick the columns side by side
To know, I don't have conditions on arrival and depart time of each eq_nb (I can't add something like datediff(second,table1.arrival_time,table2.depart_time) < X )
table1:
id | eq_nb | arival_time
-------------------------------------
1 | 25 | 05:30:15.231
-------------------------------------
2 | 50 | 06:30:15.231
-------------------------------------
3 | 7 | 07:30:15.231
-------------------------------------
1 | 25 | 08:30:15.231
-------------------------------------
5 | 27 | 09:30:15.231
-------------------------------------
table2:
id | eq_nb | depart_time
----------------------------------
1 | 25 | 05:31:15.231
----------------------------------
2 | 50 | 06:31:15.231
----------------------------------
3 | 7 | 07:31:15.231
----------------------------------
1 | 25 | 08:31:15.231
----------------------------------
desired result:
id | eq_nb | arrival_time | depart_time
-------------------------------------------------------
1 | 25 | 05:30:15.231 | 05:31:15.231
-------------------------------------------------------
2 | 50 | 06:30:15.231 | 06:31:15.231
-------------------------------------------------------
3 | 7 | 07:30:15.231 | 07:31:15.231
-------------------------------------------------------
1 | 25 | 08:30:15.231 | 08:31:15.231
--------------------------------------------------------
5 | 27 | 09:30:15.231 | NULL
--------------------------------------------------------
left join should do what you want:
select *
from table1 t1 left join
table2 t2
on t1.id = t2.id and t1.eq_nb = t2.eq_nb;
Given your data, the ids are unique, so there should be no duplication. Note: This is equivalent to your first query; left join is typically easier to follow because all the rows in the first table are in the result set.
Here is a db<>fiddle, illustrating that it works.

PostgreSQL using data from 2 tables without a common value, but a boolean

I'm new to Postgres and am trying to find a way that if one value in one table reads true, then to give me a another value in another table.
Here is one table:
itemid | pictureid1 | pictureid2 | smallpic | medpic | largepic
--------+------------+------------+----------+--------+----------
100 | 1 | 2 | t | t | t
101 | 3 | 4 | t | t | t
102 | 5 | 6 | t | t | t
103 | 7 | 8 | t | t | t
104 | 9 | 10 | t | t | t
105 | 11 | 12 | t | t | t
106 | 13 | 14 | t | t | t
107 | 15 | 16 | t | t | t
108 | 17 | 18 | t | t | t
109 | 19 | 20 | t | t | t
And here is the other:
id | size | size_url
----+--------+-----------------------------------------
1 | small | https://loremflickr.com/54/54?lock=
2 | medium | https://loremflickr.com/400/400?lock=
3 | large | https://loremflickr.com/1000/1000?lock=
I'm trying to get it where if for a particular itemid it says "true" for smallpic, then it gives me the size_url for small in the other table, with the pictureid1 and pictureid2 in the first table.
SELECT t1.pictureid1, t1.pictureid2, t2.size_url
FROM table1 t1
INNER JOIN table2 t2
ON t1.smallpic = 't' AND t2.size = 'small'
If I understood you (as the expected results are missing,
I use cte to gather url information one time and then by checking the value in item table use it in select clause.
with urls
as
(select max(case when id = 1 then url end) surl
,max(case when id = 2 then url end) murl
,max(case when id = 3 then url end) lurl
from pic_urls
)
select i.itemid
,i.pictureid1
,i.pictureid2
,case when smallpic
then (select surl from urls)
end small_url
, case when medpic
then (select murl from urls)
end med_url
, case when largepic
then (select lurl from urls)
end large_url
from items i;
I think you want to join based on the columns. Presumably, you want this for all sizes:
select t1.*,
t2s.size_url as small_url,
t2m.size_url as medium_url,
t2l.size_url as large_url
from table1 t1 left join
table2 t2s
on t2s.size = 'small' and t1.smallpic left join
table2 t2m
on t2m.size = 'medium' and t1.mediumpic left join
table2 t2l
on t2l.size = 'large' and t1.largepic ;

SQL : Comparing multiple values in one table with a single value in another Table

I have two tables Table 1 and Table 2
Table 1:
-------------------------------
| Ser | StartDate | Activity |
-------------------------------
| 1 | 2002-10-13 | 1 |
| 1 | 2002-10-13 | 2 |
| 1 | 2007-09-04 | 3 |
Table 2:
------------------------
|Ser|DateOfRegistration|
------------------------
| 1 | 2002-10-12 |
| 1 | 2007-09-02 |
Now, the result that I want is such that for Activity 1 and 2 the Date of registration should be before the Start Date and difference between the dates must be the least. Similarly, for Activity 3, the date of registration for Activity 3 should be before the start date. The result should look like this.
Table 3:
--------------------------------------------
|Ser|StartDate |DateofRegistration|Activity|
--------------------------------------------
| 1 |2002-10-13| 2002-10-12 | 1 |
| 1 |2002-10-13| 2002-10-12 | 2 |
| 1 |2002-09-04| 2002-09-02 | 3 |
How can I join Table 1 and 2 to get Table 3?
You can use outer apply:
select t1.*, t2.dateofregistration
from table1 t1 outer apply
(select top (1) t2.*
from table2 t2
where t2.ser = t1.ser and t2.dateofregistration < t1.startdate
order by t2.dateofregistration desc
) t2

Check if data for update is same as before in SQL Server

I have a table Table1:
ID | RefID | Answer | Points |
----+-------+---------+--------+
1 | 1 | 1 | 5 |
2 | 1 | 2 | 0 |
3 | 1 | 3 | 3 |
4 | 2 | 1 | 4 |
I have a result set in temp table Temp1 with same structure and have update Table1 only if for refID answer and points have changed, otherwise there should be deletion for this record.
I tried:
update table1
set table1.answer = temp1.answer,
table1.points = temp1.points
from table1
join temp1 on table1.refid = temp1.refid
where table1.answer != temp1.answer or table1.points != temp1.points
Here is a fiddle http://sqlfiddle.com/#!18/60424/1/1
However this is not working and don't know how to add the delete condition.
Desired result should be if tables not the same ex. (second row answer 2 points3):
ID | RefID | Answer | Points |
----+-------+---------+--------+
1 | 1 | 1 | 5 |
2 | 1 | 2 | 3 |
3 | 1 | 3 | 3 |
4 | 2 | 1 | 4 |
if they are same all records with refID are deleted.
Explanation when temp1 has this data
ID | RefID | Answer | Points |
----+-------+---------+--------+
12 | 1 | 1 | 5 |
13 | 1 | 2 | 0 |
14 | 1 | 3 | 3 |
EDIT: adding another id column questionid solved the update by adding this also in join.
Table structure is now:
ID | RefID | Qid |Answer | Points |
----+-------+------+-------+--------+
1 | 1 | 10 | 1 | 5 |
2 | 1 | 11 | 2 | 0 |
3 | 1 | 12 | 3 | 3 |
4 | 2 | 11 | 1 | 4 |
SQL for update is: (fiddle http://sqlfiddle.com/#!18/00f87/1/1) :
update table1
set table1.answer = temp1.answer,
table1.points = temp1.points
from table1
join temp1 on table1.refid = temp1.refid and table1.qid = temp1.qid
where table1.answer != temp1.answer or table1.points != temp1.points;
SELECT ID, refid, answer, points
FROM table1
How can I make the deletion case, if data is same ?
You need to add one more condition in the join to exactly match the column.Try this one.
update table1
set table1.answer=temp1.answer,
table1.points=temp1.points
from
table1 join temp1 on table1.refid=temp1.refid and **table1.ID=temp1.ID**
where table1.answer!=temp1.answer or table1.points!=temp1.points
I would first do the delete, and only then the update.
The reason for this is that once you've deleted all the records where the three columns are the same, your update statement becomes simpler - you only need the join, and no where clause:
DELETE t1
FROM table1 AS t1
JOIN temp1 ON t1.refid = temp1.refid
AND t1.qid = temp1.qid
AND t1.answer=temp1.answer
AND t1.points=temp1.points
UPDATE t1
SET answer = temp1.answer,
points = temp1.points
FROM table1 AS t1
JOIN temp1 ON t1.refid=temp1.refid
AND t1.qid = temp1.qid
I think from what i understood that you need to use id instead of refid or both if id is unique

mysql - get details from 2 tables with 1 query

I have 2 mysql tables:
The first table table1:
| ID | NAME |
| 1 | cat |
| 2 | mouse |
| 3 | mouse |
| 4 | mouse |
| 5 | mouse |
| 6 | mouse |
The secound table table2:
| ID | NAME_NA |
| 1 | cat |
| 2 | mouse |
| 3 | cd_rom |
| 4 | dvd_rw |
| 5 | house |
And i want to output this :
mouse - 5 entries
cat - 1 entry
cd_rom - 0 entries
dvd_rw - 0 entries
house - 0 entries
Use a LEFT JOIN:
SELECT x.name_na AS name,
COALESCE(COUNT(y.name), 0) AS num_entries
FROM TABLE2 x
LEFT JOIN TABLE1 y ON y.name = x.name_na
...to get:
name num_entries
--------------------
mouse 5
cat 1
cd_rom 0
dvd_rw 0
house 0
SELECT `table1`.`NAME`, IFNULL(COUNT(*), 0) as entries FROM
`table2` LEFT JOIN `table1` ON `table1`.`NAME` = `table2`.`NAME_NA`
GROUP BY `table1`.`NAME`;
The LEFT JOIN creates rows for each item in the "left" table (table2 here) even if there's no match in table1, and also will create multiple rows for an item in table2 if there are multiple matching rows in table1 for that item.
Then if you GROUP BY the name and use a COUNT() function, you can get the count of how many matches each item in table2 has in table1.
The IFNULL() is utilized because COUNT() will return NULL if there weren't any matches for that item in table1, so we substitute in 0 instead.