I need help with a transitive query in SQL Server.
I have a table with [ID] and [GRPID].
I would like to update a third column [NEWGRPID] based on the following logic:
For each [ID], get its GRPID;
Get all of the IDs associated with the GRPID from (1);
Set [NEWGRPID] equal to an integer (variable that is incremented by 1), for all of the rows from step (2)
The idea is several of these IDs are "transitively" linked across different [GRPID]s, and should all be having the same [GRPID].
The below table is the expected result, with [NEWGRPID] populated.
ID GRPID NEWGRPID
----- ----- ------
1 345 1
1 777 1
2 777 1
3 345 1
3 777 1
4 345 1
4 999 1
5 345 1
5 877 1
6 999 1
7 877 1
8 555 2
9 555 2
Try this code:
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
BEGIN
DROP TABLE #tmp;
END;
SELECT GRPID, count (*) AS GRPCNT
INTO #tmp
FROM yourtable
GROUP BY GRPID
UPDATE TGT
SET TGT.NEWGRPID = SRC.GRPCNT
FROM yourtable TGT
JOIN #tmp ON #tmp.GRPID = TGT.GRPID
If the values are likely to change over time you should think about a computed column or a trigger.
Related
I have a data set produced from a UNION query that aggregates data from 2 sources.
I want to select that data based on whether or not data was found in only of those sources,or both.
The data relevant parts of the set looks like this, there are a number of other columns:
row
preference
group
position
1
1
111
1
2
1
111
2
3
1
111
3
4
1
135
1
5
1
135
2
6
1
135
3
7
2
111
1
8
2
135
1
The [preference] column combined with the [group] column is what I'm trying to filter on, I want to return all the rows that have the same [preference] as the MIN([preference]) for each [group]
The desired output given the data above would be rows 1 -> 6
The [preference] column indicates the original source of the data in the UNION query so a legitimate data set could look like:
row
preference
group
position
1
1
111
1
2
1
111
2
3
1
111
3
4
2
111
1
5
2
135
1
In which case the desired output would be rows 1,2,3, & 5
What I can't work out is how to do (not real code):
SELECT * WHERE [preference] = MIN([preference]) PARTITION BY [group]
One way to do this is using RANK:
SELECT row
, preference
, [group]
, position
FROM (
SELECT row
, preference
, [group]
, position
, RANK() OVER (PARTITION BY [group] ORDER BY preference) AS seq
FROM t) t2
WHERE seq = 1
Demo here
Should by doable via simple inner join:
SELECT t1.*
FROM t AS t1
INNER JOIN (SELECT [group], MIN(preference) AS preference
FROM t
GROUP BY [group]
) t2 ON t1.[group] = t2.[group]
AND t1.preference = t2.preference
I have 2 tables and am joining them on tinnumber, but we group the records based on PSKUCD so that we have a family of tinumbers under each pskucd. We are joining with MDM table because it has updated brandname. And MDM will have only parent tinumbers. I want to use the mdm brandname from table 2 to update for parent and child tinumber's brandname in snapshot table.
Table 1 (snapshot)
Pskucd tinnum brandname
234 9999 AMZ
234 10001 AMZt
Table 2 (MDM)
tinnum bdname
9999 RMZ
Desired Output
Pskucd tinnum brandname bdname
234 9999 AMZ RMZ
234 10001 AMZt RMZ
One option might be to use outer join with first_value analytic function (sample data from line #1 - 7; query that does the job begins at line #9).
SQL> with
2 snapshot (pskucd, tinnum, brandname) as
3 (select 234, 9999 , 'AMZ' from dual union all
4 select 234, 10001, 'AMZt' from dual
5 ),
6 mdm (tinnum, bdname) as
7 (select 9999, 'RMZ' from dual)
8 --
9 select s.pskucd,
10 s.tinnum,
11 s.brandname,
12 first_value(m.bdname) over (order by null) bdname
13 from snapshot s left join mdm m on m.tinnum = s.tinnum;
PSKUCD TINNUM BRANDNAME BDNAME
---------- ---------- ---------- ----------
234 9999 AMZ RMZ
234 10001 AMZt RMZ
SQL>
Consider the table 'Table1' as below
main_id main_item_id
-------- ---------
1 101
1 102
2 105
2 105
3 105
3 106
4 101
4 101
4 102
I need to fetch main_id 2 and 4 as it has duplicate main_item_id among 1 million other records
Thanks in advance.
This will select all unique main_id's which have 2 or more identical main_item_id's:
SELECT DISTINCT T.main_id
FROM YourTable T
GROUP BY T.main_id
, T.Main_item_id
HAVING COUNT(1) > 1
Use group by clause to check the duplication
SELECT main_id, main_item_id
FROM table
GROUP BY main_id, main_item_id
HAVING count(*) > 1
I'm trying to figure it out how to put a column of max of another table into a view table!
so here is my tables:
TblProprtyDetails
id Property_id amount situation
1 1 152 true
2 1 545 false
3 2 5 false
4 2 87 true
TblExperties
id PropertyDetails_id ExpertiesDate ExpertiesPrice
1 1 2015-10-01 54
2 1 2015-11-15 546
3 2 2016-01-05 6895
4 2 2016-08-01 654
now I want to put Max of ExpertiesDate and sum of amount into a view in this structure:
id Property_id amount situation LastExpertiesDate
select
id ,Property_id,amount,situation,max(ExpertiesDate) as lastexpertisedate
from
TblProprtyDetails t1
join
TblExperties t2
on t1.id=t2.id
group by
id ,Property_id,amount,situation
You also can use cross apply
select
id ,Property_id,amount,situation,b.*
from
TblProprtyDetails t1
cross apply
(
select max(ExpertiesDate) as lastexpertisedate from table t2 where
t1.id=t2.id) b
Currently I'm working on a stored procedure to update the sort order of a table. The idea is to make sure that the correct rows are swapped.
INPUT: ToMoveID INT, Up BIT (1 up, 0 down)
SERVER: MSSQL 2012
example to use:
ID SortOrder UseForSwap
1 1 Yes
2 NULL No
3 2 Yes
4 NULL No
5 3 Yes
The idea is to put the row with ID 5 higher, the ID of 3 is unkown at this point. How Can i get the ID of the row with te first sortorder higher as the current?
Sample values: TomoveID = 5, Up = 1
After sorting the result shoud be:
ID SortOrder UseForSwap
1 1 Yes
2 NULL No
3 3 Yes
4 NULL No
5 2 Yes
Thanks in advance
You can search for a row with the biggest SortOrder that is less than SortOrder of ID 5 row in this way:
SELECT TOP 1
tbl.ID
FROM YourTable tbl
WHERE tbl.SortOrder < (SELECT SortOrder FROM YourTable tbl2 WHERE tbl2.ID = 5)
ORDER BY
tbl.SortOrder DESC