I have this table
seq Name Last_Name
1 Larry Olson
2 John Sullivan
3 Ana Ferrer
I been trying to change Larry's sequence number to 2 for example so then John should turn 1, the same if I change Larry's sequence to 3, then John will be 1 and Ana 2. What I was trying to do is use Nested Tables, but I had a hard time trying to nest 2 tables. no look, if you know a easy method I will appreciate.
If the sequence number is from a sequence and you move those values around, be sure NOT to "create" new numbers or you will break constraints.
Use a temporary table, move the rows from tab1 - the real table, to tmptab a temporary table. Update the data in tmptab. Delete the thre rows from tab1, then insert them from tmptab.
Try this without nested tables: tab1 and tmptab - WARNING practice on dummy tables first.
create table tmptab as
(select * from tab1 where seq <= 3);
update tmptab set seq =1 where name='Ana';
update tmptab set seq =2 where name='John'; -- this is just an example
commit;
delete from tab1 where seq<=3;
insert into tab1
values(seq, Name, Last_Name)
select seq, Name, Last_Name
from tmptab;
commit;
drop table tmptab;
Related
I think this is a pretty simple question but I can't figure out the right search terms to search this. This question is the most similar I could find, but it's the opposite of what I'm trying to do.
I have a query like this :
SELECT * FROM table WHERE column LIKE "val1%" OR column LIKE "val2%" OR column LIKE "val3%", ...so..on..and..on
Since it's an OR, only some of them will give matches from the column.
How can I return the matching LIKE clause with the query itself ? Like this :
SELECT *, (val1 or val2 or val3 - the matched val) FROM table WHERE column LIKE "val1%" OR column LIKE "val2%" OR column LIKE "val3%", ...so..on..and..on
Since the matching is by wildcard "%", I need to get the exact value that got the match.
If the table is this :
name
age
Mike
1
John
2
Michael
3
Milinda
4
And if the query is :
SELECT *, (the matched value) FROM table WHERE name LIKE "Mik%" OR name LIKE "Mic%" OR name LIKE "mia%"
It would return :
name
age
match
Mike
1
Mik
Michael
3
Mic
Is this possible purely with an SQLite query ? I know this can be done later after obtaining the results, but want to remove that redundancy since SQLite will already be matching anyway.
Note: The table is very large. 100,000+ rows. So performance is a big factor to get result as fast as possible. Also the OR conditions can be 5 or 10 or 15+
Create a CTE with all the match strings that you have and join to the table:
WITH cte(match) AS (VALUES ('Mik'), ('Mic'))
SELECT t.*, c.match
FROM tablename t INNER JOIN cte c
ON t.name LIKE c.match || '%'
See the demo.
You may use a case expresssion. See working fiddle below:
Schema (SQLite v3.30)
CREATE TABLE my_table (
`name` VARCHAR(7),
`age` INTEGER
);
INSERT INTO my_table
(`name`, `age`)
VALUES
('Mike', '1'),
('John', '2'),
('Michael', '3'),
('Milinda', '4');
Query #1
SELECT
*,
CASE
WHEN name LIKE "Mik%" THEN "Mik"
WHEN name LIKE "Mic%" THEN "Mic"
WHEN name LIKE "mia%" THEN "mia"
END as matched_value
FROM
my_table
WHERE
name LIKE "Mik%" OR
name LIKE "Mic%" OR
name LIKE "mia%";
name
age
matched_value
Mike
1
Mik
Michael
3
Mic
View on DB Fiddle
I have a .net web application that uses SQL Server 2008. The data table I am trying to display in a grid contains columns that are actually rows of another table. Right now, I am doing this in the BLL, reading data into data table; getting the data from another table and making it into columns of first data table and then going through each row of data in that data table to populate the new columns. Very time consuming and slow.
I believe this can be done through a query in SQL 2012 and above using "Transpose" or something similar but not sure if it is possible in 2008. I researched and tried using "pivot" but I am not good at SQL and couldn't get it to work.
This is a simplified example of DB tables and what I need to display:
Facility Table:
FacilityID
12345
67890
PartnerInfo table:
PartnerID Partner
1 Partner1
2 Partner2
3 Partner3
FacilityPartner table:
FacilityID PartnerID
12345 1
12345 3
67890 2
67890 3
Need a query to return something like:
FacilityID Partner1 Partner2 Partner3
12345 true false true
67890 false true true
Following should give some idea on pivoting the data. It doesn't give you exact true false as you asked.
declare #facility table (facilityId int)
declare #PartnerInfo table (partnerid int, partnerN varchar(1000))
declare #FacilityPartner table (facilityId int,partnerid int)
insert into #facility values (12345)
insert into #facility values (67890)
insert into #facility values (67891)
insert into #PartnerInfo values (1, 'partner1')
insert into #PartnerInfo values (2, 'partner2')
insert into #PartnerInfo values (3, 'partner3')
insert into #FacilityPartner values(12345, 1)
insert into #FacilityPartner values(12345, 3)
insert into #FacilityPartner values(67890, 2)
insert into #FacilityPartner values(67890, 3)
select f.facilityId as facid, p.PartnerN as partn, 100 as val
FROM #facility f
LEFT join #FacilityPartner fp on f.facilityId = fp.facilityId
LEFT JOIN #PartnerInfo p on p.partnerid = fp.partnerid
select facid, Partner1 , partner2,partner3 FROM
(select f.facilityId as facid, p.PartnerN as partn, 100 as val
FROM #facility f
LEFT join #FacilityPartner fp on f.facilityId = fp.facilityId
LEFT JOIN #PartnerInfo p on p.partnerid = fp.partnerid) x
PIVOT(
avg(val)
for partn in ([partner1], [partner2],[partner3])
) as pvt
The first thing to understand is, just like many other languages, SQL has a sort of "compile" process, where an execution plan is produced. An SQL query MUST be able to know the precise number and types of columns at compile time, without referencing the data (it does have some table metadata available for the compile, which is why SELECT * works).
This means what you want to do is only possible if one of two conditions is met:
You must know the precise number of partners (and the names for the columns, in this case) ahead of time. This is true even for a query using the PIVOT keyword.
You must be willing to do this in multiple steps, using dynamic SQL, where the first step looks at the data to know how many columns you'll need. Then you can build up a new query in a varchar variable, and finally execute that string using Exec() orsp_executesql(). This works because the last step invokes a new "compile" process and execution context for that string variable.
Of course there's also a third option: pivot the data in your client code. That is my preference. Most people, though, opt for option 2.
Is there any way to query directly by row number in a table in Oracle? In other words, to achieve the same effect of ordinary lookup in an array in some basic language like C or Java. I've not yet tried virtual columns.
For instance, the following is an example of an efficient query, but it wastes disk space:
create table ary (row_position_id number(10) NOT NULL,
datum binary_float NOT NULL);
declare i pls_integer;
begin
for i in 0..10000000
loop
insert into ary values (i, dbms_random.normal());
end loop;
commit;
end;
create unique index ary_rp on ary(row_position_id);
now, i'm going to create a set of query values to store in another "parameter" table:
create table query_values (qval number(10) NOT NULL);
declare i pls_integer;
begin
for i in 0..10000
loop
insert into query_values (abs(dbms_random.random() % 10000000));
end loop;
commit;
end;
now, having these query values, i'm going to query the original table
select d.* from ary d where exists (select 0 from query_values v
where d.row_position_id = v.qval);
Now, this query would be fine -- it would use INDEX UNIQUE SCAN and TABLE access by ROWID. The problem I have is that the row_position_id takes up as much space in the table blocks as the actual data (the DATUM column).
I am aware of Index-organized tables and also Virtual Columns (which cannot be used with IOTs). And, of course, things like ROWNUM and ROW_NUMBER are irrelevant here (unless I'm misunderstanding something).
Also worth pointing out, this table is static data -- once loaded, it will never change. I would likely do an ALTER TABLE ARY READ ONLY;
What I would really like is:
create table ary (datum binary_float not null);
-- load rows in a specific order
-- efficiently query this table by implicit row position
Thanks very much!
Henry
I think you're going to want to keep the extra column. Here's why:
As you said, ROWNUM and ROW_NUMBER are not applicable here because they are generated as rows are returned in the query; they will not tell you anything about insert order.
What about ROWID? ROWID is just where a row is stored - again, from the docs:
The data object number of the object
The data block in the data file in which the row resides
The position of the row in the data block (first row is 0)
The data file in which the row resides (first file is 1). The file number is relative to the tablespace.
The "position in the data block" sounds interesting, but you would have no idea what order of the data blocks that were inserted (Oracle could use whatever datablocks it can quickly make use of) so this would not be a reliable option, and even so, you'd be having to parse ROWIDs which are not human readable (e.g. in 12g they look like this: *BAGAASMCwQL+ )
Another option is ORA_ROWSCN which is interesting in that it does give you some idea of order, in terms of the system change number. However, it doesn't come for free. Just to start, you have to create your table with the ROWDEPENDENCIES option and as per docs:
ROWDEPENDENCIES Specify ROWDEPENDENCIES if you want to enable
row-level dependency tracking. This setting is useful primarily to
allow for parallel propagation in replication environments. It
increases the size of each row by 6 bytes.
The other catch with this is that you would have to have to follow each row inserted with a commit so each row would get a different SCN.
If you're willing to go this far, you'll still have to convert the rows to have indexes (starting with, say, 0 or 1) that you can use to join to other tables.
Here's a quick sample of what it would involve:
DROP TABLE temp;
CREATE TABLE temp
( a number(10)
, b varchar2(10)
)
ROWDEPENDENCIES
;
-- one commit after all rows
INSERT INTO temp VALUES (1, 'A');
INSERT INTO temp VALUES (2, 'B');
INSERT INTO temp VALUES (3, 'C');
INSERT INTO temp VALUES (4, 'D');
INSERT INTO temp VALUES (5, 'E');
INSERT INTO temp VALUES (6, 'F');
COMMIT;
SELECT X.*, ROWNUM
FROM (SELECT T.*
, ORA_ROWSCN
FROM TEMP T
ORDER BY ORA_ROWSCN
) x
;
A B ORA_ROWSCN ROWNUM
1 A 2272340 1
2 B 2272340 2
6 F 2272340 3
4 D 2272340 4
5 E 2272340 5
3 C 2272340 6
Whoops. Those rows are definitely not in the order they came in.
Now using one commit per row:
TRUNCATE TABLE temp;
INSERT INTO temp VALUES (1, 'A');
COMMIT;
INSERT INTO TEMP VALUES (2, 'B');
COMMIT;
INSERT INTO temp VALUES (3, 'C');
COMMIT;
INSERT INTO temp VALUES (4, 'D');
COMMIT;
INSERT INTO temp VALUES (5, 'E');
COMMIT;
INSERT INTO temp VALUES (6, 'F');
COMMIT;
SELECT X.*, ROWNUM
FROM (SELECT T.*
, ORA_ROWSCN
FROM TEMP T
ORDER BY ORA_ROWSCN
) x
;
A B ORA_ROWSCN ROWNUM
1 A 2272697 1
2 B 2272699 2
3 C 2272701 3
4 D 2272703 4
5 E 2272705 5
6 F 2272707 6
Better. But if you've got a significant number of rows it's not going to go in fast. (I think this is what you would do if you intentionally wanted to slow down your inserts. ;) )
I think that's about as good as you'll get trying to get around using your own column, BUT there is still hope to economize storage: you can do away with the table + index and just go with an index-organized table. It's basically an index that you query directly.
It's just this easy:
CREATE TABLE TEMP2
( A NUMBER(10)
, B VARCHAR2(10)
, CONSTRAINT PK_CONSTRAINT PRIMARY KEY (A)
)
ORGANIZATION INDEX
;
There are other parameters you'll want to consider for this as well, but for more info check out... the docs.
I would like to know how to make a single query to select something from one table or from another. For example I have Table A with the aID=2 and Table B with bID=3. So how to make the query to return the id from table A or table B for a given id = 3?
Thanks in advance
If you do not know which table to use before you're running the query, you can combine multiple queries with UNION, provided that you're selecting the same number of columns:
SELECT something FROM A WHERE aID = 3
UNION ALL
SELECT something FROM B WHERE bID = 3
If you do not want to duplicate the WHERE condition, you can use a nested query and apply the WHERE to its result:
SELECT something
FROM (SELECT aID as ID, something FROM A
UNION ALL
SELECT bID , something FROM B)
WHERE ID = 3
I want to choose a row from a certain table and order the results basing on another table.
Here are my tables:
lang1_words:
word_id - word
statuses:
word_id - status
In each table word_id corresponds to a value in another table.
Here is my query:
SELECT statuses.word_id FROM statuses, lang1_words
WHERE statuses.status >= 0
ORDER BY lang1_words.word ASC
But it return more than 1 row of the same word_id and they results are not being sorted alphabetically.
What is the problem with my query and how can I achieve my goal?
Thanks.
You need to join the two tables, one way of doing it is:
SELECT statuses.word_id FROM
statuses JOIN lang1_words ON statuses.word_id = lang1_words.word_id
WHERE statuses.status >= 0
ORDER BY lang1_words.word ASC