return resultset from function - oracle

I need to return a resultset from function and work with this resultset just like with an ordinary table.
So I need something like following:
select * from table(querydb('select * from dual'))
The querydb function should return a resultset of a query passed to it.
Can it be implemented in oracle?
Would be grateful for any information.

If you need a result set and a ref cursor won't do with a datatype called sys.anydataset. i.e what you seem to want is a pipelined function, but of course with a regular pipelined function you need to define the output structure, which in your case isn't static.
Enter anydataset. this type allows us to dynamically generate types on the fly (at hard parse time only) to allow us to define pipelined functions with varying outputs.
The coding is a bit complex unfortunately.
To start with, we define a type that will do the processing of the passed in SQL statement.
SQL> create type dyn_pipeline as object
2 (
3 atype anytype,
4
5 static function ODCITableDescribe(rtype out anytype,
6 stmt in varchar2)
7 return number,
8
9 static function ODCITablePrepare(sctx out dyn_pipeline,
10 tf_info in sys.ODCITabfuncinfo,
11 stmt in varchar2)
12 return number,
13
14 static function ODCITableStart(sctx in out dyn_pipeline,
15 stmt in varchar2)
16 return number,
17
18 member function ODCITablefetch(self in out dyn_pipeline,
19 nrows in number,
20 rws out anydataset)
21 return number,
22
23 member function ODCITableClose(self in dyn_pipeline)
24 return number
25 );
26 /
Next up, we create a package spec that will be basically your querydb function call:
SQL> create package pkg_pipeline
2 as
3
4 /*
5 * Global Types
6 */
7 -- Describe array.
8 type dynamic_sql_rec is record(cursor integer,
9 column_cnt pls_integer,
10 description dbms_sql.desc_tab2,
11 execute integer);
12 -- Meta data for the ANYTYPE.
13 type anytype_metadata_rec is record(precision pls_integer,
14 scale pls_integer,
15 length pls_integer,
16 csid pls_integer,
17 csfrm pls_integer,
18 schema varchar2(30),
19 type anytype,
20 name varchar2(30),
21 version varchar2(30),
22 attr_cnt pls_integer,
23 attr_type anytype,
24 attr_name varchar2(128),
25 typecode pls_integer);
26
27
28 /*
29 * Global Variables
30 */
31 -- SQL descriptor.
32 r_sql dynamic_sql_rec;
33
34 /*
35 * function will run the given SQL
36 */
37 function querydb(p_stmt in varchar2)
38 return anydataset pipelined using dyn_pipeline;
39
40 end pkg_pipeline;
41 /
Package created.
the types there will just hold some info about the SQL structure itself (we will be using DBMS_SQL to describe the input SQL as it has functions to get the number of columns, data types etc out of any given SQL statement.
The main type body is where the processing occurs:
SQL> create type body dyn_pipeline
2 as
3
4 /*
5 * DESC step. this will be called at hard parse and will create
6 * a physical type in the DB Schema based on the select columns.
7 */
8 static function ODCITableDescribe(rtype out anytype,
9 stmt in varchar2)
10 return number
11 is
12
13 /* Variables */
14 -- Type to hold the dbms_sql info (description)
15 r_sql pkg_pipeline.dynamic_sql_rec;
16 -- Type to create (has all the columns) of the sql query.
17 t_anyt anytype;
18 -- SQL query that will be made up from the 2 passed in queries.
19 v_sql varchar2(32767);
20
21 begin
22
23 /*
24 * Parse the SQL and describe its format and structure.
25 */
26 v_sql := replace(stmt, ';', null);
27
28 -- open, parse and discover all info about this SQL.
29 r_sql.cursor := dbms_sql.open_cursor;
30 dbms_sql.parse( r_sql.cursor, v_sql, dbms_sql.native );
31 dbms_sql.describe_columns2( r_sql.cursor, r_sql.column_cnt, r_sql.description );
32 dbms_sql.close_cursor( r_sql.cursor );
33
34 -- Start to create the physical type.
35 anytype.BeginCreate( DBMS_TYPES.TYPECODE_OBJECT, t_anyt );
36
37 -- Loop through each attribute and add to the type.
38 for i in 1 .. r_sql.column_cnt
39 loop
40
41 t_anyt.AddAttr(r_sql.description(i).col_name,
42 case
43 when r_sql.description(i).col_type in (1,96,11,208)
44 then dbms_types.typecode_varchar2
45 when r_sql.description(i).col_type = 2
46 then dbms_types.typecode_number
47 when r_sql.description(i).col_type in (8,112)
48 then dbms_types.typecode_clob
49 when r_sql.description(i).col_type = 12
50 then dbms_types.typecode_date
51 when r_sql.description(i).col_type = 23
52 then dbms_types.typecode_raw
53 when r_sql.description(i).col_type = 180
54 then dbms_types.typecode_timestamp
55 when r_sql.description(i).col_type = 181
56 then dbms_types.typecode_timestamp_tz
57 when r_sql.description(i).col_type = 182
58 then dbms_types.typecode_interval_ym
59 when r_sql.description(i).col_type = 183
60 then dbms_types.typecode_interval_ds
61 when r_sql.description(i).col_type = 231
62 then dbms_types.typecode_timestamp_ltz
63 end,
64 r_sql.description(i).col_precision,
65 r_sql.description(i).col_scale,
66 r_sql.description(i).col_max_len,
67 r_sql.description(i).col_charsetid,
68 r_sql.description(i).col_charsetform );
69 end loop;
70
71 t_anyt.EndCreate;
72
73 -- set the output type to our built type.
74 ANYTYPE.BeginCreate(dbms_types.TYPECODE_TABLE, rtype);
75 rtype.SetInfo(null, null, null, null, null, t_anyt,
76 dbms_types.TYPECODE_OBJECT, 0);
77 rtype.EndCreate();
78
79 return ODCIConst.Success;
80
81 end ODCITableDescribe;
82
83
84 /*
85 * PREPARE step. Initialise our type.
86 */
87 static function ODCITableprepare(sctx out dyn_pipeline,
88 tf_info in sys.ODCITabfuncinfo,
89 stmt in varchar2)
90 return number
91 is
92
93 /* Variables */
94 -- Meta data.
95 r_meta pkg_pipeline.anytype_metadata_rec;
96
97 begin
98
99 r_meta.typecode := tf_info.rettype.getattreleminfo(
100 1, r_meta.precision, r_meta.scale, r_meta.length,
101 r_meta.csid, r_meta.csfrm, r_meta.type, r_meta.name
102 );
103
104 sctx := dyn_pipeline(r_meta.type);
105 return odciconst.success;
106
107 end;
108
109
110 /*
111 * START step. this is where we execute the cursor prior to fetching from it.
112 */
113 static function ODCITablestart(sctx in out dyn_pipeline,
114 stmt in varchar2)
115 return number
116 is
117
118 /* Variables */
119 r_meta pkg_pipeline.anytype_metadata_rec;
120 v_sql varchar2(32767);
121 begin
122
123 v_sql := replace(stmt, ';', null);
124 pkg_pipeline.r_sql.cursor := dbms_sql.open_cursor;
125 dbms_sql.parse(pkg_pipeline.r_sql.cursor, v_sql, dbms_sql.native);
126 dbms_sql.describe_columns2(pkg_pipeline.r_sql.cursor,
127 pkg_pipeline.r_sql.column_cnt,
128 pkg_pipeline.r_sql.description);
129
130 -- define all the columns found to let Oracle know the datatypes.
131 for i in 1..pkg_pipeline.r_sql.column_cnt
132 loop
133
134 r_meta.typecode := sctx.atype.GetAttrElemInfo(
135 i, r_meta.precision, r_meta.scale, r_meta.length,
136 r_meta.csid, r_meta.csfrm, r_meta.type, r_meta.name
137 );
138
139 case r_meta.typecode
140 when dbms_types.typecode_varchar2
141 then
142 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, '', 32767);
143 when dbms_types.typecode_number
144 then
145 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as number));
146 when dbms_types.typecode_date
147 then
148 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as date));
149 when dbms_types.typecode_raw
150 then
151 dbms_sql.define_column_raw(pkg_pipeline.r_sql.cursor, i, cast(null as raw), r_meta.length);
152 when dbms_types.typecode_timestamp
153 then
154 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as timestamp));
155 when dbms_types.typecode_timestamp_tz
156 then
157 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as timestamp with time zone));
158 when dbms_types.typecode_timestamp_ltz
159 then
160 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as timestamp with local time zone));
161 when dbms_types.typecode_interval_ym
162 then
163 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as interval year to month));
164 when dbms_types.typecode_interval_ds
165 then
166 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as interval day to second));
167 when dbms_types.typecode_clob
168 then
169 case pkg_pipeline.r_sql.description(i).col_type
170 when 8
171 then
172 dbms_sql.define_column_long(pkg_pipeline.r_sql.cursor, i);
173 else
174 dbms_sql.define_column(pkg_pipeline.r_sql.cursor, i, cast(null as clob));
175 end case;
176 end case;
177 end loop;
178
179 -- execute the SQL.
180 pkg_pipeline.r_sql.execute := dbms_sql.execute(pkg_pipeline.r_sql.cursor);
181
182 return odciconst.success;
183
184 end ODCITablestart;
185
186
187 /*
188 * FETCH step.
189 */
190 member function ODCITablefetch(self in out dyn_pipeline,
191 nrows in number,
192 rws out anydataset)
193 return number
194 is
195
196 /* Variables */
197 -- Buffers to hold values.
198 v_vc_col varchar2(32767);
199 v_num_col number;
200 v_date_col date;
201 v_raw_col raw(32767);
202 v_raw_error number;
203 v_raw_len integer;
204 v_int_ds_col interval day to second;
205 v_int_ym_col interval year to month;
206 v_ts_col timestamp;
207 v_tstz_col timestamp with time zone;
208 v_tsltz_col timestamp with local time zone;
209 v_clob_col clob;
210 v_clob_offset integer := 0;
211 v_clob_len integer;
212 -- Metadata
213 r_meta pkg_pipeline.anytype_metadata_rec;
214
215 begin
216
217 if dbms_sql.fetch_rows( pkg_pipeline.r_sql.cursor ) > 0
218 then
219
220 -- Describe to get number and types of columns.
221 r_meta.typecode := self.atype.getinfo(
222 r_meta.precision, r_meta.scale, r_meta.length,
223 r_meta.csid, r_meta.csfrm, r_meta.schema,
224 r_meta.name, r_meta.version, r_meta.attr_cnt
225 );
226
227 anydataset.begincreate(dbms_types.typecode_object, self.atype, rws);
228 rws.addinstance();
229 rws.piecewise();
230
231 -- loop through each column extracting value.
232 for i in 1..pkg_pipeline.r_sql.column_cnt
233 loop
234
235 r_meta.typecode := self.atype.getattreleminfo(
236 i, r_meta.precision, r_meta.scale, r_meta.length,
237 r_meta.csid, r_meta.csfrm, r_meta.attr_type,
238 r_meta.attr_name
239 );
240
241 case r_meta.typecode
242 when dbms_types.typecode_varchar2
243 then
244 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_vc_col);
245 rws.setvarchar2(v_vc_col);
246 when dbms_types.typecode_number
247 then
248 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_num_col);
249 rws.setnumber(v_num_col);
250 when dbms_types.typecode_date
251 then
252 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_date_col);
253 rws.setdate(v_date_col);
254 when dbms_types.typecode_raw
255 then
256 dbms_sql.column_value_raw(pkg_pipeline.r_sql.cursor, i, v_raw_col,
257 v_raw_error, v_raw_len);
258 rws.setraw(v_raw_col);
259 when dbms_types.typecode_interval_ds
260 then
261 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_int_ds_col);
262 rws.setintervalds(v_int_ds_col);
263 when dbms_types.typecode_interval_ym
264 then
265 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_int_ym_col);
266 rws.setintervalym(v_int_ym_col);
267 when dbms_types.typecode_timestamp
268 then
269 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_ts_col);
270 rws.settimestamp(v_ts_col);
271 when dbms_types.typecode_timestamp_tz
272 then
273 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_tstz_col);
274 rws.settimestamptz(v_tstz_col);
275 when dbms_types.typecode_timestamp_ltz
276 then
277 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_tsltz_col);
278 rws.settimestampltz(v_tsltz_col);
279 when dbms_types.typecode_clob
280 then
281 case pkg_pipeline.r_sql.description(i).col_type
282 when 8
283 then
284 loop
285 dbms_sql.column_value_long(pkg_pipeline.r_sql.cursor, i, 32767, v_clob_offset,
286 v_vc_col, v_clob_len);
287 v_clob_col := v_clob_col || v_vc_col;
288 v_clob_offset := v_clob_offset + 32767;
289 exit when v_clob_len < 32767;
290 end loop;
291 else
292 dbms_sql.column_value(pkg_pipeline.r_sql.cursor, i, v_clob_col);
293 end case;
294 rws.setclob(v_clob_col);
295 end case;
296 end loop;
297
298 rws.endcreate();
299
300 end if;
301
302 return ODCIConst.Success;
303
304 end;
305
306 /*
307 * CLOSE step. close the cursor.
308 */
309 member function ODCITableClose(self in dyn_pipeline)
310 return number
311 is
312
313
314 begin
315 dbms_sql.close_cursor( pkg_pipeline.r_sql.cursor );
316 pkg_pipeline.r_sql := null;
317 return odciconst.success;
318 end ODCITableClose;
319
320 end;
321 /
Type body created.
once this is done, you can query like:
SQL> select * from table(pkg_pipeline.querydb('select * from dual'));
D
-
X
SQL> select * from table(pkg_pipeline.querydb('select * from v$mystat where rownum <= 2'));
SID STATISTIC# VALUE
---------- ---------- ----------
230 0 1
230 1 1

If I understand you correctly, you want to do this:
select * from (select * from dual)
...with the caveat that the subquery is in some way dynamic? You can do this using a PL/SQL block, using a reference cursor:
declare
subQuery varchar2(1000);
mainQuery varchar2(1000) := 'select * from (';
type myRefCursor is ref cursor;
myResultset myRefCursor;
myField1 FIELDTYPE;
...
myFieldN FIELDTYPE;
begin
-- Generate this dynamically
subQuery := 'select * from dual';
-- Create main query and open cursor
mainQuery := mainQuery || subQuery || ')';
open myResultset for mainQuery;
-- Loop through records
loop
fetch myResultset into myField1, ..., myFieldN;
exit when myResultset%NOTFOUND;
-- Do something with the record data
dbms_output.put_line(myField1 || ' ... ' || myFieldN);
end loop;
close myResultset;
end;
/
Note that rather than using fetch into with individual variables, you can populate an entire record at once, provided you can define the record's field types. That is, if you have created a custom type or your record's type matches a table you already have in your schema. For the latter, you can use:
myRecord someTable%ROWTYPE;
...in the declaration block, then change the fetch into statement to:
fetch myResultset into myRecord;
...and access record fields using dot notation (e.g., myRecord.some_field_name).
You say in your comments that the dynamic SQL bit is from the results of some other query. Therefore, in my example code, you could use a regular cursor to loop over these data to create the subQuery variable in each instance... Although, incidentally, is there any reason why what you're trying to achieve can't be done with a simple join?

Related

An allocation problem of people into groups getting them to meet as little as possible

I have been trying to solve this for quite a while without success.
I have not found (I searched though) theory that could help me on wikipedia.
Here is the problem.
I have a group of n players (more than 7)
I have a game (diplomacy for those who know !) that requires 7 players, one for these roles : E,F,G,I,A,R and T (countries in fact)
I want to set up a tournament (many games).
There will be n games.
(*) Every player gets into 7 different games, with different role each time
(**) Every game gets 7 different players
=> That is very easy to do.
However, when things get tough, is when you want to limit interactions between players.
What I want is any player to interact (interact = play in same game) at most with one other player.
(In other words, I want to prevent players from making such deals : "I help you in game A, you help me in game B")
So:
Question 1 : For which n is this possible ? (obviously at least 50)
Question 2 : When it is possible, how do you do it ?
Question 3 : What is the algo to minimize these interactions when it is not possible ?
For the record, I did implement a try-and-error program in python (using recursion), working quite well, but I never can get maximum intearctions between players limited to 1 (endless calculations)
thanks for any help !
PS This is no homework, it is for actually designing game tournaments :-)
I did some doodling and I think; If I understand you correctly, that you can do the following:
28 people to do the 7 roles/7 games meeting other players only once.
If the position of a person in the following games is allocated to distinct roles then no person plays the same role in the games they play.
Python
# -*- coding: utf-8 -*-
"""
https://stackoverflow.com/questions/71143133/an-allocation-problem-of-people-into-groups-getting-them-to-meet-as-little-as-po
Created on Sat Feb 19 21:15:02 2022
#author: paddy3118
By hand to get the algo:
0 roles, 0 people for 0 interactions
1 role, 1 person
2 roles, 3 people: p0+p1, p1+p2
3 roles, 012, 134, 235 = 6 people
4 roles, 0123, 1456, 2478, 3579 = 10 people
"""
from itertools import count
def new_person():
yield from count()
def people_allocation(roles: int=4):
games, new_p = [], count()
for i in range(roles):
game = []
games.append(game)
for j in range(i):
game.append(games[j][i])
for _ in range(i, roles):
game.append(next(new_p))
return games, next(new_p)
for roles in range(8):
print(f"Roles = {roles}:")
games, people = people_allocation(roles)
print(f" Takes {people} people in the following games")
print(' ',
', '.join('+'.join(f"P{x}" for x in game) for game in games))
Output
Roles = 0:
Takes 0 people in the following games
Roles = 1:
Takes 1 people in the following games
P0
Roles = 2:
Takes 3 people in the following games
P0+P1, P1+P2
Roles = 3:
Takes 6 people in the following games
P0+P1+P2, P1+P3+P4, P2+P4+P5
Roles = 4:
Takes 10 people in the following games
P0+P1+P2+P3, P1+P4+P5+P6, P2+P5+P7+P8, P3+P6+P8+P9
Roles = 5:
Takes 15 people in the following games
P0+P1+P2+P3+P4, P1+P5+P6+P7+P8, P2+P6+P9+P10+P11, P3+P7+P10+P12+P13, P4+P8+P11+P13+P14
Roles = 6:
Takes 21 people in the following games
P0+P1+P2+P3+P4+P5, P1+P6+P7+P8+P9+P10, P2+P7+P11+P12+P13+P14, P3+P8+P12+P15+P16+P17, P4+P9+P13+P16+P18+P19, P5+P10+P14+P17+P19+P20
Roles = 7:
Takes 28 people in the following games
P0+P1+P2+P3+P4+P5+P6, P1+P7+P8+P9+P10+P11+P12, P2+P8+P13+P14+P15+P16+P17, P3+P9+P14+P18+P19+P20+P21, P4+P10+P15+P19+P22+P23+P24, P5+P11+P16+P20+P23+P25+P26, P6+P12+P17+P21+P24+P26+P27
Assuming that n ≥ 78 or so, the following simple hill climbing algorithm with periodic restarts will return a solution.
The algorithmic idea is to initialize games where each player plays each role exactly once, then drive the number of conflicts to zero (where a conflict is a player playing two roles in a single game, or two players meeting each other more than once) by choosing two random games and a random role and swapping the players involved. We restart every 107 steps because that seems to work well in practice.
Doubtless we could do a little better with constraint programming.
#include <algorithm>
#include <array>
#include <cstdlib>
#include <iostream>
#include <random>
#include <vector>
constexpr int r = 7;
int main() {
int n;
std::cin >> n;
if (n <= r * (r - 1)) {
return EXIT_FAILURE;
}
std::uniform_int_distribution<int> uniform_game(0, n - 1);
std::uniform_int_distribution<int> uniform_role(0, r - 1);
std::random_device device;
std::default_random_engine engine(device());
while (true) {
std::vector<std::array<int, r>> games(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < r; j++) {
games[i][j] = (i + j) % n;
}
}
int badness = 0;
std::vector<std::vector<int>> pair_counts(n, std::vector<int>(n, 0));
auto count = [&badness, &games, &pair_counts](int i, int j, int increment) {
for (int k = 0; k < r; k++) {
if (k == j) continue;
auto [a, b] = std::minmax(games[i][j], games[i][k]);
badness -= pair_counts[a][b] > (a != b ? 2 : 0);
pair_counts[a][b] += increment;
badness += pair_counts[a][b] > (a != b ? 2 : 0);
}
};
for (int i = 0; i < n; i++) {
for (int j = 0; j < r; j++) {
count(i, j, 1);
}
}
for (long t = 0; t < 10000000; t++) {
int i1;
int i2;
do {
i1 = uniform_game(engine);
i2 = uniform_game(engine);
} while (i1 == i2);
int j = uniform_role(engine);
auto swap_players = [&]() {
count(i2, j, -2);
count(i1, j, -2);
std::swap(games[i1][j], games[i2][j]);
count(i1, j, 2);
count(i2, j, 2);
};
int old_badness = badness;
swap_players();
if (old_badness < badness) {
swap_players();
} else if (badness < old_badness) {
std::cerr << badness << '\n';
}
if (badness <= 0) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < r; j++) {
if (j) std::cout << ' ';
std::cout << games[i][j];
}
std::cout << '\n';
}
return EXIT_SUCCESS;
}
}
}
}
Sample output:
21 38 61 75 77 2 22
70 31 75 7 15 59 69
28 52 29 73 59 23 40
61 45 16 65 35 15 55
12 72 44 45 46 14 10
57 1 3 38 11 6 49
20 6 7 26 0 74 18
54 73 67 58 6 55 75
73 77 63 36 3 0 45
37 57 55 28 34 43 7
17 46 36 66 16 7 48
74 9 24 22 17 73 15
36 50 4 69 28 65 6
59 62 12 32 24 20 51
38 8 59 17 10 19 39
6 53 21 70 13 71 56
55 33 49 59 5 27 36
15 71 33 54 43 18 29
60 36 8 40 71 51 67
19 49 9 34 45 53 60
41 26 73 21 72 35 19
14 64 42 15 57 63 62
44 11 23 27 9 16 21
2 7 68 9 63 52 54
35 18 2 3 60 64 17
29 17 50 41 31 61 57
47 10 32 25 75 28 35
30 48 64 6 32 39 44
46 22 71 35 20 31 11
43 76 41 11 47 60 14
56 2 1 33 74 10 37
51 41 39 0 33 70 34
32 5 18 31 23 76 68
65 43 53 8 27 46 73
63 44 26 5 70 24 28
62 75 66 71 44 3 41
16 69 54 13 22 41 5
58 19 52 57 36 22 70
42 25 22 44 55 56 76
4 30 35 51 76 13 9
72 13 17 62 40 77 43
53 16 10 68 50 58 64
64 47 70 55 38 40 20
50 59 14 48 1 9 71
40 63 19 76 69 1 12
24 35 69 56 68 57 27
67 34 15 72 56 66 32
68 3 46 37 25 21 59
77 54 47 19 4 44 31
76 67 38 46 52 50 33
25 15 77 1 51 26 23
3 61 40 4 53 5 74
45 51 74 29 48 68 47
75 0 57 23 30 8 72
13 27 28 14 19 67 2
9 20 72 42 65 33 3
49 58 48 20 41 37 77
22 12 37 67 39 47 53
26 42 11 61 37 36 13
1 60 5 39 29 75 46
48 40 65 10 54 34 26
23 66 60 50 42 54 24
8 74 13 63 49 32 50
27 29 58 12 7 38 42
7 4 45 24 64 25 8
71 24 30 47 2 49 16
31 28 56 60 12 48 0
10 23 62 49 67 69 61
34 21 31 30 58 62 1
66 70 27 18 61 30 25
0 37 76 64 66 29 65
69 39 43 2 26 45 58
39 65 25 74 62 11 52
5 56 20 52 14 17 30
33 68 6 77 8 12 66
11 55 51 53 18 72 63
52 32 0 43 21 42 4
18 14 34 16 73 4 38
Eventually I think I solved this problem.
I explain it here to help any other person facing such a problem.
I used two "classical" algorithms.
try-and-error to get a first configuration of low quality, with iterations that tries first those players with fewest intearctions and which are already in more games
hill-climibing to improve quality of configuration (making swaps between a conflicting and not conflicting player, or two conflicting players if all players are conflicting) and selecting randomly, keeping the result of swap only if it increases quality - quality is worst number of conflicts (2 usually) and number of occurences)
I reach the following conclusion :
always a solution above 100
never a solution below 90
Thanks for all support you provided !

Print Next Line When Error Occurs

Using exception I need to print the next value after an error occurred.
For example
FOR i IN 1..50
IF MOD(i,5) <> 0 THEN
dbms_output.put_line(i);
I need to print all values except values divisible by 5.
Thanks in advance.
If this would be code in pl/sql then you are very close - just try to add: BEGIN, LOOP, END IF, END LOOP and END clauses:
begin
FOR i IN 1..50 LOOP
IF MOD(i,5) <> 0 THEN
dbms_output.put_line(i);
end if;
end loop;
end;
/
1
2
3
4
6
7
8
9
11
12
13
14
16
17
18
19
21
22
23
24
26
27
28
29
31
32
33
34
36
37
38
39
41
42
43
44
46
47
48
49

Row sum in PIVOT query

Please Help me i am trying to create pivot but not success.
query
select
t.g_no,
t.sz,
t.DT,
t.Qty
from gp123 t
Result
4480 46 4/24/2017 30
4480 42 4/24/2017 28
4480 40 4/24/2017 37
4480 44 4/24/2017 26
4480 50 4/24/2017 17
4480 48 4/24/2017 2
Required result
Gate Pass No. Date 40 42 44 46 48 50 Total
4480 24-Apr-17 37 28 26 30 2 17 140
4500 25-Apr-17 187 140 155 127 99 85 793
4537 25-Apr-17 141 97 139 172 141 159 849
4538 26-Apr-17 90 141 122 148 172 151 824
4542 26-Apr-17 1 60 118 63 32 3 277
Use the SUM() OVER () analytic function to get the total and then use PIVOT to convert the rows to columns:
SELECT *
FROM ( SELECT g_no AS "Gate Pass No.",
sz,
DT AS "Date",
Qty,
SUM( qty ) OVER ( PARTITION BY g_no, DT ) AS Total
FROM gp123
)
PIVOT ( SUM( qty ) FOR sz IN ( 40, 42, 44, 46, 48, 50 ) )
... or simply:
select g_no, dt, "40", "42", "44", "46", "48", "50",
"40" + "42" + "44" + "46" + "48" + "50" total
from gp123 t
pivot (sum(qty) for sz in (40, 42, 44, 46, 48, 50));

Pascal reading text file, bad number format

I created text file using pascal, wrote to that text file some lines with numbers
and now I'm trying to read the first line of text file and pascal giving me error BAD NUMBER FORMAT.
Here's code:
program Text_files;
{
procedure CreateFile(f1:string);
var f:text;
x,x1,n:integer;
begin
assign(f,f1);
rewrite(f);
n:=1;
for x1:= 1 to 5 do
begin
for x:= 1 to 20 do
begin
write(f,n,' ');
n:=n+1;
end;
writeln(f);
end;
close(f);
end;
}
procedure ReadFile(f1:string);
var f:text;
n:integer;
begin
assign(f,f1);
reset(f);
while not eoln(f) do
begin
read(f,n);
write(n,' ');
end;
close(f);
end;
begin
//CreateFile('NewFile.txt');
ReadFile('NewFile.txt');
Readln;
end.
I tried to change n variable to string type and it worked i read the first line of text file, but I want that read data to be integer type. What is the problem?
NewFile.txt DATA:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
You can not read numbers when you open a text file. Even if you'd try to read it as a file of records it wouldn't work because those records don't have the same length.
1 is just on byte in size and 100 is three bytes. Additionally you have the spaces and probably EOLs.
So, you would have to change the
procedure CreateFile(f1:string);
var f:file of integer;
x,x1,n:integer;
begin
assign(f,f1);
rewrite(f);
n:=1;
for x1:= 1 to 100 do
begin
write(f,x1);
end;
close(f);
end;
And then
procedure ReadFile(f1:string);
var f:file of integer;
n:integer;
begin
assign(f,f1);
reset(f);
while not eof(f) do
begin
read(f,n);
write(n,' ');
end;
close(f);
end;
begin
CreateFile('NewFile.txt');
ReadFile('NewFile.txt');
end.
This should solve your problem. But it has a drawback: the file-contents are not human readable. If that matters to you for some reason you have to do it the hard way. I.e. you keep your version of CreateFile and rewrite only ReadFile
procedure ReadFile(f1:string);
procedure getNumsFromString(s:string);
var
sTmp: string;
iPos: integer;
i : integer;
begin
repeat
iPos=pos(#32,s);
sTmp=copy(s,1,iPos);
s=copy(s,iPos+1,length(s));
i=strtoInt(sTmp);
write(i,#32);
until (length(s)=0);
end;
var f:text;
s:string;
begin
assign(f,f1);
reset(f);
while not eof(f) do
begin
read(f,s);
getNumsFromString(s);
writeln();
end;
close(f);
end;
the code is untested but you get the idea. Hope it helps
Procedure Reading;
Var
n: longint;
Begin
assign(input,'NewFile.txt');
reset(input);
While not EoF{EoLn} do
begin
read(n);
write(n,' ');
end;
End;

oracle analytics how to return this rows

I am writing this query for DWH purpose.
SELECT
YEAR
,MONTH
,WEEK
,C.CPG_PK CPG
,C.DEP_PK DEPT
,T.CUST_ID CUST_ID
,D1.R_ID R_ID
,Decode(d2.AT_CODE,'3',FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE)) AS P1
,decode(d2.AT_CODE,'2',FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE)) AS IC
,decode(d2.AT_CODE,'1',FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE)) AS B1
,decode(FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE), 2 , d2.AT_CODE) AS P2
,decode(FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE), 5 , d2.AT_CODE) AS B2
,COUNT(DISTINCT A.CUST_ID) TOTAL_ACC
,COUNT(DISTINCT T.TXN_PK) TOTAL_TXN
,SUM(AM_AMOUNT) TOTAL_AMT
FROM T_HEADER T
,CUST_MASTER A
,TX_DETAILS1 D1
,TX_DETAILS2 D2
,CPG_MASTER C
WHERE A.TYPE = 0
AND T.CUST_ID = A.CUST_ID
AND T.TXN_PK= 5001
AND T.TXN_PK= D1.TXN_PK
AND T.TXN_PK= D2.TXN_PK
AND D1.CPG_PK = C.CPG_PK
AND D1.OP = 1
GROUP BY
YEAR
,MONTH
,WEEK
,C.CPG_PK
,C.DEP_PK
,t.CUST_ID
,D1.R_ID
,Decode(d2.AT_CODE,'3',FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE))
,decode(d2.AT_CODE,'2',FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE))
,decode(d2.AT_CODE,'1',FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE))
,decode(FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE), 2 , d2.AT_CODE)
,decode(FUNC1.GET_ATT(d2.AT_CODE,D2.VAL_CODE), 5 , d2.AT_CODE)
the generated output as follows
YEAR MONTH WEEK CPG DEPT CUST_ID R_ID P1 IC B1 P2 B2 TOTAL_ACC TOTAL_TXN TOTAL_AMT
2012 08 32 127 -1 10019 3665 134 1 1
2012 08 32 127 -1 10019 3665 135 1 1
2012 08 32 127 -1 10019 3665 723 1 1
2012 08 32 127 -1 10019 3665 714 1 1
2012 08 32 127 -1 10019 3665 21 1 1
2012 08 32 128 -1 10019 3665 134 1 1
2012 08 32 128 -1 10019 3665 135 1 1
2012 08 32 128 -1 10019 3665 723 1 1
2012 08 32 128 -1 10019 3665 714 1 1
2012 08 32 128 -1 10019 3665 21 1 1
here the values are repeating i tried with possible group by.
the required ouput is
YEAR MONTH WEEK CPG DEPT CUST_ID R_ID P1 IC B1 P2 B2 TOTAL_ACC TOTAL_TXN TOTAL_AMT
2012 08 32 127 -1 10019 3665 21 714 723 134 1 1
2012 08 32 127 -1 10019 3665 21 714 723 135 1 1
2012 08 32 128 -1 10019 3665 21 714 723 134 1 1
2012 08 32 128 -1 10019 3665 21 714 723 135 1 1
the main thing is year,month,week,cpg,dept,cust_id,r_id ,p1,ic,b1,p2,b2 it should be unique row. Is it achievable using analytical functions or do I need to write pl/sql
Saw this, and I think I have an answer for you. So what you are wanting is SQL to take a table that looks like:
Year Col_1 Col_2 Col_3
2012 A
2012 B
2012 C
And transform it into:
Year Col_1 Col_2 Col_3
2012 A B C
What you can do (for the above example) is the following:
Select
Year,
Max(Col_1) as C1,
Max(Col_2) as C2,
Max(Col_3) as C3
From
Table_1
Group By
Year
This will work with out trouble if you ONLY have 1 record in each. Otherwise, you might have to figure out if you need to use MAX, MIN, SUM, or an alternative aggregation function.
If all the data was in one column and you wanted it in one column, you could use a similar technique:
Table_1
Year Col_1
2012 A
2012 B
2012 C
Code
Select
Year,
Max(Case When Col_1 = 'A' Then 'A' End) as A_Col,
Max(Case When Col_1 = 'B' Then 'B' End) as B_Col,
Max(Case When Col_1 = 'C' Then 'C' End) as C_Col
From
Table_1
Group By
Year
Note that Decodes should work in place of Case statements, but I think Cases are easier to read.

Resources