How to Batch select in oracle sql - sql

i have one mock table table_a as below:
id a b c d
1 11 22 33 44
2 22 33 44 55
3 33 44 55 66
4 44 55 66 77
5 55 66 77 88
6 66 77 88 99
7 77 88 99 100
8 88 99 11 22
suppose the known info is c and d, if i want to get entry id 2 & 6, i can run
' select * from table_a where (c, d) in ((44,55), (88,99))'.
Here is my question. If this table has 1 million rows , and i want to get 1 thousand rows out , just by knowing their c and d values, is there any better way to do it? My concern to use above script to do it is performance. Thanks.

If you have an index on (c, d), then Oracle should use the index for the in query:
create index idx_table_a_c_d on table_a(c, d);

Related

SQL query to extract matching diagonal pairs in SQL Server database

I have a database table (mytable) with 2 columns x and y as shown below, from which I intend to extract rows with matching diagonal pairs of (x,y) and (y,x) e.g., 4 21 and 21 4
x y
86 86
27 27
45 45
95 95
11 11
18 8
85 85
2 2
77 77
91 91
15 15
84 84
51 51
32 32
35 35
8 8
92 92
67 67
62 62
33 33
13 13
15 11
18 18
3 3
38 38
80 80
34 34
6 6
72 72
14 12
44 44
4 22
90 90
47 47
78 78
23 3
42 42
56 56
79 79
55 55
65 65
17 17
64 64
4 4
28 28
19 19
17 9
36 36
25 25
81 81
60 60
48 48
5 5
88 88
7 19
21 21
29 29
52 52
9 17
9 9
13 13
16 10
1 1
31 31
46 46
7 7
58 58
23 23
87 87
83 83
66 66
93 93
24 2
98 98
53 53
20 6
61 61
20 20
96 96
99 99
73 73
2 24
14 14
71 71
5 21
22 4
75 75
6 20
97 97
41 41
26 26
22 22
8 18
74 74
40 40
21 5
94 94
76 76
49 49
11 15
59 59
89 89
68 68
24 24
37 37
12 12
63 63
43 43
16 16
100 100
39 39
25 1
69 69
54 54
50 50
30 30
10 10
I have tried the accepted code on stackoverflow here (enter link description here) on my mytable which gives me the expected results on Oracle DB.
select least(x, y) as x, greatest(x, y) as y
from mytable
group by least(x, y), greatest(x, y)
having count(*) = 2
union all
select x, y
from mytable
where not exists (select 1 from mytable mytable2 where mytable2.y = mytable.x and mytable2.x = mytable2.y)
order by x asc;
Now I need to execute the same query on MS SQL DB but according to my understanding MS SQL DB does not support the least and greatest functions. I have tried to use the case conditions, for instance for the first part of the SQL query on the link provided, I am considering the below but so far I cannot replicate similar results:
select x,y,z
from (
select x, y,
case
when (x < y) then x
when (y > x) then y
end as z
from mytable
group by x, y
) as t
Any suggestions on what I need to consider to complete the query in SQL Server database, so that I produce the final output as below?
It would also be great if somebody has an idea on how I can use SQL's lag() function to assist me in achieving the same result. For instance I am trying something like below.
;with t1 as (
select x as x1, y as y1, lag(x,1) over(order by x asc) as z1
from mytable
),
t2 as (
select x as x2, y as y2, lag(y,1) over(order by x asc) as z2
from mytable
)
select t1.*,t2.*
from t1 full outer join t2 on t1.x1 = t2.x2
Expected output:
x y
2 24
4 22
5 21
6 20
8 18
9 17
11 15
13 13
The equivalent of the functions LEAST() and GREATEST() is to use CASE expressions:
SELECT CASE WHEN x < y THEN x ELSE y END AS x,
CASE WHEN x > y THEN x ELSE y END AS y
FROM mytable
GROUP BY CASE WHEN x < y THEN x ELSE y END,
CASE WHEN x > y THEN x ELSE y END
HAVING COUNT(*) = 2 -- change to COUNT(*) > 1 if each combination may exist more than twice
ORDER BY x, y;
The above query will return a row for a combination of (x, y) that exists twice even if (y, x) does not exist.
If this is not what you want, use a self join and UNION ALL:
SELECT DISTINCT t1.*
FROM mytable t1 INNER JOIN mytable t2
ON t2.x = t1.y AND t2.y = t1.x
WHERE t1.x < t1.y
UNION ALL
SELECT x, y
FROM mytable
WHERE x = y
GROUP BY x, y
HAVING COUNT(*) > 1
ORDER BY x, y;
See the demo.

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

Using SQL SMS How do I return a list of numbers using low and high columns

I have a table SUB_Inst with columns id, low and high. How would I query the low and high numbers returning a new column with a record for each number from low to high?
Current table SUB_Inst
id low High
1 55 63
2 232 234
3 4 7
etc.
Desired Results
id low High Num_list
1 55 63 55
1 55 63 56
1 55 63 57
1 55 63 58
1 55 63 59
1 55 63 60
1 55 63 61
1 55 63 62
1 55 63 63
2 232 234 232
2 232 234 233
2 232 234 234
3 4 7 4
3 4 7 5
3 4 7 6
3 4 7 7
etc.
I tried something like this:
SELECT Low, HIGH,
(SELECT CAST(number as varchar)+','
FROM NUMBERS
WHERE number >= Low and number <= High
FOR XML PATH(''))
FROM SUB_Inst
but it returned all the numbers in one field like this which won't work:
Low High Num_List
24 27 24,25,26,27,
34 36 34,35,36,
10 17 10,11,12,13,14,15,16,17,
34 36 34,35,36,
65 67 65,66,67,
502 504 502,503,504,
56 59 56,57,58,59,
Thank you.
I think you want this :
SELECT id,low,high,number as Num_List
FROM SUB_Inst , NUMBERS
where low<=number and high>=number