How to update every rows which has a number greater than or equal to the joining table? - sql

Here is an example of the tables I am joining together (note: the tables have the exact same schema but are in different databases, I am trying to combine them):
Database 1 Table
UniqID UniqID2 Number
100 150 1
100 151 2
Database 2 Table
UniqID UniqID2 Number
100 152 2
100 153 3
I am trying to merge Table2 into Table1 and I'm joining on Table1.UniqID = Table2.UniqID. I don't want any overlapping values in the Number column, this is what I want the result to look like:
Table 1
UniqID UniqID2 Number
100 150 1
100 151 2
100 152 3
100 153 4
This is the query I have so far, but it only updates the row in Table 2 where the Number = 2 and doesn't increment the Number = 3 row. How can I adjust my query to do so?
UPDATE db2
Set db2.Number = db2.Number +
(SELECT MAX(Number) FROM [Database 1]..db1 WHERE UniqID = db2.UniqID)
FROM [Database 2]..table db2
INNER JOIN [Database 1]..Table db1
ON db1.UniqID = db2.UniqID
AND db1.Number = db2.Number
And this is what my Database 2 Table results look like right now:
Database 2 Table
UniqID UniqID2 Number
100 152 3
100 153 3
Basically, the only difference is that I want the Number = 3 to be Number = 4 in the second column.

I think you want a union all query and insert:
insert into table1(UniqID, UniqID2, Number)
select t2.UniqID, t2.UniqID2,
(x.maxn + row_number() over (order by (select null) ))
from table2 t2 cross join
(select max(number) as maxn from table1) x;

A different appraoch could be
UPDATE t2
SET t2.Number = t1.T1Number + 1
FROM table2 t2
INNER JOIN (SELECT uniqid, uniqid2, number as T1Number from Table1
union
SELECT uniqid, uniqid2, number as T1Number from Table2
) t1
ON t1.uniqid = t2.uniqid and t1.UniqID2 = t2.UniqID2-1

one more approach which works in SQL 2012..
Demo here
;With cte
as
(select *
from
#t
union all
select *
from #t1
)
select uniqid,uniqid2,
case when lag(number) over (order by uniqid,uniqid2) is null then number
when lead(number) over (order by uniqid,uniqid2) is null
then number+1 else lead(number) over (order by uniqid,uniqid2) end as nextnumber
from cte

Related

wants to pick most closest record in group of records in single table which input criteria

we have a table and there is possibility that one record can have multiple copies means same record can exist in table with multiple entries but their criteria will be different criteria is decided using three main parameters.income,score,no_months.these columns are integer.and we are grouping them by giving unique code to same records profile.
if one input is eligible for multiple profiles then we need to pick which is most matching to criteria.
Sample Data.
id
name
income
score
no_months
group_code
22
abc
1000
500
6
abccode
23
abc
900
600
12
abccode
24
bca
1000
600
12
bcacode
Desired Results
id
name
income
score
no_months
group_code
23
abc
900
600
12
abccode
24
bca
1000
600
12
bcacode
Note: id 23 row has 2 columns which values are greater than id 22 row that is why id 23 was picked although id 23 has less income
Only those records should be display which columns have more count of greater values than other row if group_code is same.
I have tried using multiple order by with cte as more columns needs to display like image city etc. but its not working
Select a single row for the Name or a winner of multiple rows. Winner is one with max score of wins when compared to others in a triangle join. Provided 2 rows has the same criteria, a row with the lesser id wins.
select *
from tbl t
where id in (
-- winners
select winid
from tbl t1
join tbl t2 on t1.name = t2.name and t1.id < t2.id
join lateral (
select case when sign(t1.income - t2.income) + sign(t1.score - t2.score) + sign(t1.no_months - t2.no_months) >= 0
then t1.id else t2.id end winid
) w on 1=1
group by winid
order by count(*) desc
limit 1)
or not exists(select 1 from tbl t3 where t3.name = t.name and t3.id <> t.id)

SQL Select from 1 table rows with 2 specific column value that are not equal

I have a table
id number name update_date
1 123 asd 08.05.18
2 412 ddd 08.05.18
3 123 dsa 14.05.18
4 125 dsa 05.05.18
Whole table consist from that rows like that. I need to select row 1 and 3 because I need different update_dates but same number. How to do that? I need to see the changes from specific Number between 2 update dates 08.05.18 and 14.05.18. I have more update dates in my table.
I tried:
SELECT *
FROM legal_entity_history a
JOIN legal_entity_history b ON a.BIN = b.BIN
WHERE ( a.update_date <> b.update_date AND
a.update_date = "08.05.18" AND
b.update_date = "14.05.18" )
A relatively simple method is:
select leh.*
from legal_entity_history leh
where exists (select 1
from legal_entity_history leh2
where leh2.number = leh.number and leh2.update_date <> leh.update_date
);
For performance, you want an index on legal_entity_history(number, update_date).
TRY THIS: Assuming that same number may not appear more than once under same update_date, so, you can achieve that using GROUP BY with HAVING as below
SELECT t.*
FROM test t
INNER JOIN (SELECT number
FROM test
GROUP BY number
HAVING COUNT(DISTINCT update_date) > 1) t1 ON t1.number = t.number
OUTPUT:
id number name update_date
1 123 asd 08.05.18
3 123 dsa 14.05.18

shifting some columns one record back or forward

I have a table with about 8000 rows and 15 columns. After I have inserted the data I saw that my data was wrong after a number of records (let's say 1000) some column values belong to the previous record some thing like this:
A B C (A+B)
==================================
1 1 2
2 2 4
3 3 6
4 4 8
5 5
6 6 10
7 7 12
8 8 14
9 9 16
Now I have to either move some column values a record back or forward and I don't actually have much option testing it I'm afraid I may overwrite some data and ruin the whole table
I should do something like this but for about 7000 records:
update table1
set B = (select B from table1 where id = 1000)
where id = 999
Any ideas?
If you know the ids are sequential with no gaps, you can use a join to look up the value you want:
update t1
set c = tt1.c
from table1 t1 join
table1 t2
on t1.id = t2.id - 1
where t1.id > 1000;
If you cannot trust the ids, you can create the appropriate sequential number without gaps using row_number():
with toupdate as (
select t.*, row_number() over (order by id) as seqnum
from table1
)
update t1
set c = tt1.c
from toupdate t1 join
toupdate t2
on t1.seqnum = t2.seqnum - 1
where t1.id > 1000;
Create another table with the same fields as the table in question. Insert the bad records. Fix the data in the new table. Update the real table from the new one.
First, you should always test your statements before making definate changes to your data. You could start a transaction and only commit when certain it went well or make a copy of your table (select * into x from y) and test on that.
To answer your question, try something like this;
WITH dataToUpdate AS(
SELECT RowNr ,
DATA,
DataFromPreviousRow = FIRST_VALUE(data) OVER (ORDER BY RowNr ROWS 1 PRECEDING)
FROM dbo.test
)
UPDATE dataToUpdate
SET data = dataToUpdate.DataFromPreviousRow;

How to SELECT top N rows that sum to a certain amount?

Suppose:
MyTable
--
Amount
1
2
3
4
5
MyTable only has one column, Amount, with 5 rows. They are not necessarily in increasing order.
How can I create a function, which takes a #SUM INT, and returns the TOP N rows that sum to this amount?
So for input 6, I want
Amount
1
2
3
Since 1 + 2 + 3 = 6. 2 + 4 / 1 + 5 won't work since I want TOP N ROWS
For 7/8/9/10, I want
Amount
1
2
3
4
I'm using MS SQL Server 2008 R2, if this matters.
Saying "top N rows" is indeed ambiguous when it comes to relational databases.
I assume that you want to order by "amount" ascending.
I would add a second column (to a table or view) like "sum_up_to_here", and create something like that:
create view mytable_view as
select
mt1.amount,
sum(mt2.amount) as sum_up_to_here
from
mytable mt1
left join mytable mt2 on (mt2.amount < mt1.amount)
group by mt1.amount
or:
create view mytable_view as
select
mt1.amount,
(select sum(amount) from mytable where amount < mt1.amount)
from mytable mt1
and then I would select the final rows:
select amount from mytable_view where sum_up_to_here < (some value)
If you don't bother about performance you may of course run it in one query:
select amount from
(
select
mt1.amount,
sum(mt2.amount) as sum_up_to_here
from
mytable mt1
left join mytable mt2 on (mt2.amount < mt1.amount)
group by mt1.amount
) t where sum_up_to_here < 20
One approach:
select t1.amount
from MyTable t1
left join MyTable t2 on t1.amount > t2.amount
group by t1.amount
having coalesce(sum(t2.amount),0) < 7
SQLFiddle here.
In Sql Server you can use CDEs to make it pretty simple to read.
Here is a CDE I did to sum up totals used in sequence. The CDE is similar to the joins above, and holds the total up to any given index. Outside of the CDE I join it back to the original table so I can select it along with other fields.
;with summrp as (
select m1.idx, sum(m2.QtyReq) as sumUsed
from #mrpe m1
join #mrpe m2 on m2.idx <= m1.idx
group by m1.idx
)
select RefNum, RefLineSuf, QtyReq, ProjectedDate, sumUsed from #mrpe m
join summrp on summrp.idx=m.idx
In SQL Server 2012 you can use this shortcut to get a result like Grzegorz's.
SELECT amount
FROM (
SELECT * ,
SUM(amount) OVER (ORDER BY amount ASC) AS total
from demo
) T
WHERE total <= 6
A fiddle in the hand... http://sqlfiddle.com/#!6/b8506/6

SQL Group By Question

I have a table that has the below columns.
I need to find out those people that has More than 2 ApplicantRowid with same jobcategoryrowid and AssessmentTest should have atleast one row NULL with Different Appstatusrowid's.
The result should look exeactly like the below table.
Rowid ApplicantRowid JobCategoryRowid AssessmentTestRowid AppstatusRowid
10770598 6952346 157 3 5
11619676 6952346 157 NULL 6
select t.*
from
(
select ApplicantRowid, JobCategoryRowid
from tbl
group by ApplicantRowid, JobCategoryRowid
having count(AssessmentTestRowid) < count(*)
and count(distinct AppstatusRowid) > 1
) x
inner join t on t.ApplicantRowid = x.ApplicantRowid
and t.JobCategoryRowid = x.JobCategoryRowid
COUNT does not include NULLs, so count(AssessmentTestRowid) < count(*) ensures there is at least a NULL
count(distinct AppstatusRowid) > 1 ensure there are different AppstatusRowids