Insert incrementing index rows from one table into another range based table - sql

i got two tables like this:
how can i insert new rows into Table A from Table B matching the given range defined in Table A ?
Even i thought this would be pretty straight-foward i cant find anything about ths -.-
Excuse my bad english and Thank u in advance

First of all, copy Table A to Table A_Ranges. This way it won't interfere with the result data, and you will be able to reuse it in the future.
Once Table A_Ranges is ready, clear table A.
The following will match each record from B, with the appropriate range:
INSERT INTO A(Range_From, Range_To, payload, IDX, Detail)
SELECT A_Ranges.Range_From, A_Ranges.Range_To, A_Ranges.payload, B.IDX, B.Detail
FROM A_Ranges
INNER JOIN B ON B.IDX BETWEEN A_Ranges.Range_From and A_Ranges.Range_To

Related

How can I delete duplicate rows in the same table that have identical CLOB data?

I have a table in Oracle of which one of the columns (named CONTENTSTRING) is a CLOB. However, some of the rows in this table have identical data in this column. What I'd like to do is remove all the rows except for one that have this identical data. How can I accomplish this?
Googling around, I see a ton of examples for comparing two columns. I also see examples comparing between two different tables. What I don't see is an example using one table and just comparing the rows! I do think I might need to use this function: dbms_lob.compare. However, I'm still not sure how I can set this function up.
From a programmer's perspective, I would think maybe I should do something like:
SELECT CONTENTSTRING FROM TABLE_ALPHA A
and then somehow do another select from the same table as TABLE_ALPHA B, and then use dmbs_lob.compare to compare the two columns. If the row numbers are different AND the column contents are equal, then the row from TABLE_ALPHA B can be deleted.
I think that's the right approach, but how exactly would I write this out in Oracle using SQL? I would appreciate any help or resources on this. Thanks!
DELETE
FROM TABLE_ALPHA A
WHERE EXISTS (
SELECT 1 FROM TABLE_ALPHA B
WHERE DBMS_LOB.COMPARE(A.CONTENTSTRING, B.CONTENTSTRING) = 0
AND A.ROWID > B.ROWID
)
This deletes all dublicates except first one.
This answer assumes that you have a primary key field in the source table (I called it id).
You can use a subquery to list the ids of the duplicated records : this works by self-joining the table with dbms_lob.compare and a comparison clause on the id. If duplicate rows exist with the same CLOB content, all ids but the most ancient (ie the smallest) are selected. The outer query just deletes the selected ids. The NVL will consider NULL contents as duplicates (if that's not relevant for your use case, just remove them).
DELETE FROM TABLE_ALPHA
WHERE id IN (
SELECT b.id
FROM TABLE_ALPHA a
INNER JOIN TABLE_ALPHA b
ON
(
(a.contentString IS NULL AND b.contentString IS NULL)
OR dbms_lob.compare(a.CONTENTSTRING, b.CONTENTSTRING) = 0
)
AND b.id > a.id
);
See this db fiddle.

Conditional Join act as a mater table

Hi sorry I could not find a way to best title what I am looking for.
Anyway I have an idea of how to do something but I just need a new pair of eyes to look at what I am trying to do to see if it is possible. I basically have two tables one which has a load of text and numbers and another one which acts like a master table so if anything is found in the second table use that otherwise only use what is found in the first table. However I am unsure how to complete the select statement for this, I know i can go down the route of doing two separate select statements and union them up together but there must be an easier way. After playing around I have a query which I think may work but I am unsure if I have missed something. For example we have Table A and Table B (B holding the master data)
SELECT DISTINCT
A.ID,
COALESCE(B.PROD, A.PROD) AS PROD
COALESCE(B.TEXT1, A.TEXT1) AS TEXT1,
COALESCE(B.NUMBER, A.NUMBER) AS NUMBER
FROM
TABLEA A
FULL OUTER JOIN TABLEB B ON A.PROD = B.PROD
Now what I want is the statement to pick up the following information
Anything found in Table A but not in Table B
Anything found in Table B not in Table A
Anything in Table B as the master which is found in
in Table A
I added a full outer join as there maybe items in table B not in Table A
Will the query work, i have checked against out data and it seems to work however I am not sure if i have missed something.
Thanks

Insert with select, dependent on the values in the table inserting into EDITED

So I need to figure out how to insert into a table, from another table, with a where clause that requires me to access the table that I am inserting into. I tried an alias from the table I am inserting into, but I quickly found out that you cannot do that. Basically, what I want to check is that the values that I am inserting into the table match a particular field within the table that I am inserting into. Here is what I've tried:
INSERT INTO "USER"."TABLE1" AS A1
SELECT *
FROM "USER"."TABLE2" AS A2
WHERE A2."HIERARCHYLEVEL" = 2
AND A2."PARENT" = A1."INSTANCE"
Obviously, this was to no avail. I've tried a couple other queries, but they didn't me anywhere, either. Any help would be much appreciated.
EDIT:
I would like to add rows to this table, not add columns to the table. The two tables are of the exact same structure -- in fact, I extracted the data already in table1 from table2. What I have in table1 currently is a bunch of records who have NO PARENT, but an instance. What I want to add is all the records who have a parent in table2 that are equal to the instance in table 1.
Currently there is no way to join on a table when inserting. The solution with the subselect where you select from the table, is the correct.
Aliasing the table you want to change is only possible with UPDATE, UPSERT and MERGE. For these operations it makes sense, as you need to match a column and then decide if you need to update it or insert something instead. In your example the line from table1 that you match is not relevant, as you don't want to change it, so from the statement point of view it is not really relevant that the table you use in your subselect is the same that the one you insert into.
As alternative, I can suggest you following solution, which is equivalent with yours:
INSERT INTO "user"."table1"
SELECT
A1."ROOT",
A1."INSTANCE",
A1."PARENT",
A1."HIERARCHYLEVEL"
FROM "user"."table2" AS A1
WHERE A1."INSTANCE" in (select "PARENT" from "user"."table1")
AND A2."HIERARCHYLEVEL" = 2
This gave me the answer I was looking for, although I am sure there is an easier -- or more efficient -- way to do it.
INSERT INTO "user"."table1"
SELECT
A1."ROOT",
A1."INSTANCE",
A1."PARENT",
A1."HIERARCHYLEVEL"
FROM "user"."table2" AS A1,
"user"."table1" AS A2
WHERE A1."INSTANCE" = A2."PARENT"
AND A2."HIERARCHYLEVEL" = 2

Replace certain values by the means of a table with replacement values

I have a table with data in it. Generally the values are correct but sometimes we need to modify them. The modifications are saved in a second table.
I wanted to create a query that dynamically replaces the values if they exist in the replacement table.
This is what my query design looks like but it doesn't work:
This is my query code:
SELECT
b.Pos,
b.Posten,
IsNull(c.Wert_Neu, b.Bez1) AS Bez1,
IsNull(c.Wert_Neu, b.Bez2) AS Bez2,
IsNull(c.Wert_Neu, b.Bez3) AS Bez3,
b.Wert,
b.Einheit
FROM
Table_Values b LEFT JOIN
Table_Replacements c ON b.Bez1 = c.Wert_Alt AND b.Bez2 = c.Wert_Alt AND b.Bez3 = c.Wert_Alt
Where is my logical error? It doesn't replace the values. I assume it has something to do with the joins all going there without OR, but OR would be too costly for performance.
Anyone with a better idea?
Looks like what you want to do is to replace each of the values with the one that appears in the replacement table, but you have three separate columns, and each of those three values will have a different corresponding entry in the replacement table. So you will have to link to that table three different times, once for each value, to link to its replacement, something like:
SELECT
b.Pos,
b.Posten,
IsNull(c.Wert_Neu, b.Bez1) AS Bez1,
IsNull(d.Wert_Neu, b.Bez2) AS Bez2,
IsNull(e.Wert_Neu, b.Bez3) AS Bez3,
b.Wert,
b.Einheit
FROM
Table_Values b
LEFT JOIN Table_Replacements c on b.bez1=c.wert_alt
LEFT JOIN Table_Replacements d on b.bez2=d.wert_alt
LEFT JOIN Table_Replacements e on b.bez3=e.wert_alt
It will be important that your replacement table have an index on wert_alt so that those links can be done efficiently.
Another possibility is to actually store the replacement values in your main data table. So the fields in it would be:
bez1
bez1Replacement
bez2
bez2Replacement
...
Maybe have a trigger on the table so that on any insert or update, the trigger looks up each of the three replacement values from the replacement table and adds them to the main data record. That would not be exactly normalized, but it would speed up your query. But, you may not need to do that at all. The above query is probably efficient enough if you do have that index.

Correct spelling mistakes in a column based on another table in postgresql

My postgresql table has a (cityname) column. the values in the (cityname) column has some spelling mistakes. Each and every record of column (cityname) needs to be corrected. Another table has a column that contains all correct city names. Based on this table the spelling mistakes of the first table are needed to be corrected.
You need a column which can relate rows in table A (with the mistakes) to table B with the correct data. Lets assume you have the city_id column which does this job.
update table_A
set add1 = table_b.correct_add1
from table_A as j_table_A
join table_B on table_B.city_id = table_A.city_id
where j_table_A.primary_key_column = table_A.primary_key_column
you basically reference table_A twice. there is no good reason to do this, but I have found that if you need to pull data from joins, then during an update this is the easiest way.
Edited after comment:
Since you have no good way of associating the correct data to the data that needs fixing (like a city_id), then you need to work on your join condition and perhaps introduce a regex. there is a link here which may be of some use