Foreign key value count for each row in a table - sql

I'm trying to generate a table which returns a count for the preceding instances of the foreign key value up to and including the foreign key value on that row.
ForeignIDValue is non-nullable.
I've tried table variables and common table expressions but it gets long winded and messy.
Is there a more elegant and concise way of doing it?
So table A
PrimaryKeyValue ForeignIDValue ProgressiveForeignIDValueCount
15 42 NULL
16 42 NULL
17 43 NULL
18 42 NULL
19 42 NULL
20 42 NULL
24 42 NULL
26 42 NULL
27 42 NULL
29 42 NULL
30 42 NULL
31 42 NULL
32 42 NULL
35 42 NULL
36 42 NULL
37 42 NULL
38 42 NULL
39 42 NULL
40 44 NULL
41 45 NULL
42 46 NULL
43 45 NULL
Needs to become Table B
PrimaryKeyValue ForeignIDValue ProgressiveForeignIDValueCount
15 42 1
16 42 2
17 43 1
18 42 3
19 42 4
20 42 5
24 42 6
26 42 7
27 42 8
29 42 9
30 42 10
31 42 11
32 42 12
35 42 13
36 42 14
37 42 15
38 42 16
39 42 17
40 44 1
41 45 1
42 46 1
43 45 2

SELECT PrimaryKeyValue, ForeignIDValue,
ProgressiveForeignIDValueCount = ROW_NUMBER() OVER
(PARTITION BY ForeignIDValue ORDER BY PrimaryKeyValue)
FROM dbo.[your table name]
ORDER BY PrimaryKeyValue, ProgressiveForeignIDValueCount;
Example db<>fiddle

Related

Update seq based on criteria - Oracle SQL

I have a table:
table1
id element_id element_value lx_seq line_num
59 A301-01 Test 1 25
59 A301-01 Test 1 26
59 K301-01 Test 1 27
59 K301-01 1 28
59 K302-01 18105678982800 1 28
59 K304-01 TOPS 1 28
59 K305-01 7 1 28
59 K306-01 888P 1 28
60 K301-01 Test 1 27
60 K301-01 1 28
60 K302-01 18105678982800 1 28
60 K304-01 TOPS 1 28
60 K305-01 7 1 28
60 K306-01 888P 1 28
61 K301-01 Test 1 27
61 K301-01 1 27
62 K301-01 Test 1 27
62 K301-01 1 28
62 K301-01 18105678982800 1 29
62 K304-01 TOPS 1 29
62 K305-01 7 1 29
62 K306-01 888P 1 29
This is the output table:
table2
id element_id element_value lx_seq line_num
59 A101-01 Test 1 25
59 A101-01 Test 1 26
59 K301-01 Test 1 27
59 K301-01 2 28
59 K302-01 18105678982800 2 28
59 K304-01 TOPS 2 28
59 K305-01 7 2 28
59 K306-01 888P 2 28
60 K301-01 Test 1 27
60 K301-01 2 28
60 K302-01 18105678982800 2 28
60 K304-01 TOPS 2 28
60 K305-01 7 2 28
60 K306-01 888P 2 28
61 K301-01 Test 1 27
61 K301-01 1 27
62 K301-01 Test 1 27
62 K301-01 2 28
62 K301-01 18105678982800 3 29
62 K304-01 TOPS 3 29
62 K305-01 7 3 29
62 K306-01 888P 3 29
I need to update lx_seq if and only if in 1 id, we have multiple K3 + line_num combination. It should not work for any other elements like A1.
How can I increase lx_seq based on the above condition in Oracle SQL?
you need dense_rank() function for lx_seq column as below
dense_rank() over (partition by id order by line_num) as lx_seq,
and it's not to hold an already calculated column within a column, that violates the normalization rule for database.
You could do something like following using dense_rank
--first select all not K3 rows and keep lx_seq same
SELECT id, element_id, element_value, lx_seq, line_num
from table1 where element_id not like 'K3%'
UNION ALL
--select K3 rows and based on id and line_num generate rank
SELECT id, element_id, element_value,
dense_rank() over (partition by id, line_num order by line_num) lx_seq,
line_num
from table1 where element_id like 'K3%'
Example Update statement:
MERGE INTO table1 A USING
(
SELECT id, element_id, element_value,
dense_rank() over (partition by id, line_num order by line_num) lx_seq,
line_num
FROM table1
WHERE element_id LIKE 'K3%'
) B
ON (A.id = B.id AND A.line_num = B.line_num AND A.element_id = B.element_id)
WHEN MATCHED THEN
UPDATE SET A.lx_seq = B.lx_seq;

SQL Server : create new column category price according to price column

I have a SQL Server table with a column price looking like this:
10
96
64
38
32
103
74
32
67
103
55
28
30
110
79
91
16
71
36
106
89
87
59
41
56
89
68
32
80
47
45
77
64
93
17
88
13
19
83
12
76
99
104
65
83
95
Now my aim is to create a new column giving a category from 1 to 10 to each of those values.
For instance the max value in my column is 110 the min is 10. Max-min = 100. Then if I want to have 10 categories I do 100/10= 10. Therefore here are the ranges:
10-20 1
21-30 2
31-40 3
41-50 4
51-60 5
61-70 6
71-80 7
81-90 8
91-100 9
101-110 10
Desired output:
my new column called cat should look like this:
price cat
-----------------
10 1
96 9
64 6
38 3
32 3
103 10
74 7
32 3
67 6
103 10
55 5
28 2
30 3
110 10
79 7
91 9
16 1
71 7
36 3
106 10
89 8
87 8
59 5
41 4
56 5
89 8
68 6
32 3
80 7
47 4
45 4
77 7
64 6
93 9
17 1
88 8
13 1
19 1
83 8
12 1
76 7
99 9
104 10
65 6
83 8
95 9
Is there a way to perform this with T-SQL? Sorry if this question is maybe too easy. I searched long time on the web. So either the problem is not as simple as I imagine. Either I entered the wrong keywords.
Yes, almost exactly as you describe the calculation:
select price,
1 + (price - min_price) * 10 / (max_price - min_price + 1) as decile
from (select price,
min(price) over () as min_price,
max(price) over () as max_price
from t
) t;
The 1 + is because you want the values from 1 to 10, rather than 0 to 9.
Yes - a case statement can do that.
select
price
,case
when price between 10 and 20 then 1
when price between 21 and 30 then 2
when price between 31 and 40 then 3
when price between 41 and 50 then 4
when price between 51 and 60 then 5
when price between 61 and 70 then 6
when price between 71 and 80 then 7
when price between 81 and 90 then 8
when price between 91 and 100 then 9
when price between 101 and 110 then 10
else null
end as cat
from [<enter your table name here>]

How to divide a result set into equal parts?

I have a table new_table
ID PROC_ID DEP_ID OLD_STAFF NEW_STAFF
1 15 43 58 ?
2 19 43 58 ?
3 29 43 58 ?
4 31 43 58 ?
5 35 43 58 ?
6 37 43 58 ?
7 38 43 58 ?
8 39 43 58 ?
9 58 43 58 ?
10 79 43 58 ?
How I can select all proc_ids and update new_staff, for example
ID PROC_ID DEP_ID OLD_STAFF NEW_STAFF
1 15 43 58 15
2 19 43 58 15
3 29 43 58 15
4 31 43 58 15
5 35 43 58 23
6 37 43 58 23
7 38 43 58 23
8 39 43 58 28
9 58 43 58 28
10 79 43 58 28
15 - 4(proc_id)
23 - 3(proc_id)
28 - 3(proc_id)
58 - is busi
where 15, 23, 28 and 58 staffs in one dep
"how to divide equal parts"
Oracle has a function, ntile() which splits a result set into equal buckets. For instance this query puts your posted data into four buckets:
SQL> select id
2 , proc_id
3 , ntile(4) over (order by id asc) as gen_staff
4 from new_table;
ID PROC_ID GEN_STAFF
---------- ---------- ----------
1 15 1
2 19 1
3 29 1
4 31 2
5 35 2
6 37 2
7 38 3
8 39 3
9 58 4
10 79 4
10 rows selected.
SQL>
This isn't quite the solution you want but you need to clarify your requirements before it's possible to provide a complete answer.
update new_table
set new_staff='15'
where ID in('1','2','3','4')
update new_table
set new_staff='28'
where ID in('8','9','10')
update new_table
set new_staff='23'
where ID in('5','6','7')
Not sure if this is what you mean.

SQL I need the highest number from column + count duplicate values

I'm looking for a query that gives a list of the RepairCost for each BikeNumber,
but the duplicate values have to be counted as well. So BikeNumber 18 cost total 22 + 58 = 80
Id RepairCost BikeNumber
16 82 23
88 51 20
12 20 19
33 22 **18**
40 58 **18**
69 41 17
10 2 16
66 35 15
If i understand the question, the query is pretty simple:
SELECT BikeNumber, SUM(RepairCost)
FROM YourTable
GROUP BY BikeNumber

trying to get user assign to under another user

I am trying to write a sql query in which I want all the list of uid assigned under another uid from the below given table
uid rid assTo
1 1 NULL
2 2 1
3 1 2
6 11 3
7 11 1
17 11 1
18 11 1
19 11 1
21 11 1
22 2 1
23 11 22
24 2 22
25 10 24
26 10 24
27 11 26
28 11 26
29 10 24
30 11 3
31 11 29
32 11 29
33 11 29
34 11 29
35 11 29
36 11 29
37 11 29
38 11 29
39 11 29
40 11 29
41 11 29
47 11 2
48 11 2
50 11 26
51 11 2
52 11 26
53 11 29
55 11 1
56 11 1
57 11 652
68 11 652
70 11 652
71 11 652
72 11 2
74 1 1
75 11 2
76 11 652
80 11 652
86 11 652
87 11 1
88 11 26
89 11 29
I want all the list of uid assigned to another uid i.e. designated in assto column in above table
How can I implement it?
My query
select u1.assignto 'assignto',u2.userid 'userid'
from users u1 join users u2
on u1.assignto=u2.userid
My desired output is that when i search uid = 1
i should the list of the uid available in the above table.
IN solution:
select * from tablename
where uid in (select assTo from tablename)
Self JOIN solution:
select distinct t1.*
from tablename t1
JOIN tablename t2 ON t1.uid= t2.assTo
EXISTS solution (similar to IN):
select *
from tablename t1
where exists (select 1 from tablename t2
where t2.assTo = t1.uid)