SQL replace value in a field in a row if it exists, else create a row and populate that value - sql

My request is a little strange and specific, please bear with me.
I have an Access 2003 database with a Comments table that has several hundred thousand lines in it. There are several fields - let's call them A, B, C, D and comment. Columns A-C form the PK of the table. Thus, you could have 5, 10, or 50 rows which have different comments, but all pertain to the A-C PK.
I have another table called CORE which contains a table core that has fields A, B, C, D (A-C PK) and comment_value_insert.
What I want to do:
In Comments, for each "set" of identical A-C rows (Field D can differ), if none of their comment values matches a certain value (let's call it critical), then look up the same row in CORE and insert into the comments table a new row with A-D and Comments.comment = core.comment_value_insert.
I'm not even sure if this is possible with SQL (perhaps VBA? Hence the tag). Any advice anyone?
For further clarification please ask away.
Huge thanks in advance.
EDIT
To demonstrate exactly what I want:
If my Comments table looks like
A | B | C | D | Comment
1 2 3 b val1
1 2 3 x val2
1 2 3 a val3
2 9 8 z val4
2 9 8 a val5
3 3 3 x val6
END
And my CORE Table looks like
A | B | C | D | Comment_value_insert
1 2 3 u critical1
2 9 8 t critical2
4 8 6 x critical3
END
Then I'd want the critical1 row from CORE to be inserted into Comments, as well as the critical2 row, but not the critical3 row.
Then the final product in the Comments table will be
A | B | C | D | Comment
1 2 3 b val1
1 2 3 x val2
1 2 3 a val3
1 2 3 u critical1
2 9 8 z val4
2 9 8 a val5
2 9 8 t critical2
3 3 3 x val6
END

Try something like this for the INSERT part. For the UPDATE part you should provide more information.
-- EDIT --
INSERT INTO Comments ( A, B, C, D, Comment )
SELECT DISTINCT C.A, C.B, C.C, C.D, C.comment_value_insert
FROM Core AS C INNER JOIN Comments as C1 ON C.A = C1.A and C.B = C1.B and C.C = C1.C
WHERE NOT EXISTS (SELECT * FROM Comments AS O WHERE O.Comment = "Critical" AND O.A = C.A AND O.B = C.B AND O.C = C.C);
Regards,

** This version worked for me **
INSERT INTO comments
SELECT a,
b,
c,
d,
comment_value_insert AS comment
FROM core
WHERE EXISTS (SELECT comments.*
FROM comments
WHERE core.c = comments.c
AND core.b = comments.b
AND core.a = comments.a)
AND NOT EXISTS (SELECT comments.*
FROM comments
WHERE core.c = comments.c
AND core.b = comments.b
AND core.a = comments.a
AND core.comment_value_insert = comments.comment)

Related

Update table column that is used for ordering according to alphabetical order on a second table

So I have two tables (A and B) that have a relation of n-n.
So there is a third table (C) that is used to connect both tables.
Table A and B both have an Id and a name.
Table C has IDA, IDB and an Order, the number that is used to sort and that is user given.
My issue is that I need to migrate table C since I just added that order column and so I need to give every line an ordering number, according to the B name.
So if table A has:
Id Name
1 A
2 B
3 C
And Table B has:
Id Name
1 J
2 L
3 M
And table C has:
IdA IdB Order
1 2 0
1 1 0
1 3 0
2 1 0
2 3 0
I need a query that updates table C to be more like:
IdA IdB Order
1 2 2
1 1 1
1 3 3
2 1 1
2 3 2
I have a query that can basically do what i want but it leaves me with "gaps"
reading my results above i get:
IdA IdB Order
1 2 2
1 1 1
1 3 3
2 1 1
2 3 3
I think this should work for what you need:
With ToUpdate As
(
Select C.*,
Row_Number() Over (Partition By C.IdA Order By B.Name) As NewOrder
From C
Join B On B.Id = C.IdB
)
Update C
Set "Order" = U.NewOrder
From ToUpdate U
Where U.IdA = C.IdA
And U.IdB = C.IdB
(In full disclosure, I'm not terribly familiar with postgres, but I think this should be valid).

SQL Server query with repeated values

I have a lookup table (Table A) and a table that stores the actual values (Table B). The issue I'm facing is Table B can store multiple values (comma-separated) from Table A.
So if Table A has for example 2 columns:
Code Value
------------
1 Dog
2 Cat
3 Bird
4 Bear
...and Table B can have something like this:
Record # Code
--------------------
1 2
2 3,4
3 1,4
4 3
5 1,2,3,4
When I loop through Table B, I want my output to look like this:
Record # Code Value
-------------------------------------
1 2 Cat
2 3 Bird
2 4 Bear
3 1 Dog
3 4 Bear
4 3 Bird
5 1 Dog
5 2 Cat
5 3 Bird
5 4 Bear
In other words, I want a record from Table B to return as many times as many comma-separated values it has from Table A.
What is the best and the most efficient way of achieving this?
TIA,
-TS.
If you don't have (or want) a Split/Parse function, here is an in-line approach
Example
Select A.[Record #]
,Code = B.RetVal
,C.Value
From TableB A
Cross Apply (
Select RetSeq = Row_Number() over (Order By (Select null))
,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>' + replace(A.[Code],',','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) B
Join TableA C on B.RetVal=C.Code
Returns

Pairs with no duplicates grouped together

I have a table
ID GROUPID NAME
== ======= ========
1 100 A
2 100 B
3 200 C
4 200 D
5 300 E
6 100 F
I would like to create a table containing the permutation pairs within a group without any pairs that are the same on both first and second that looks like this:
PAIRID FIRST SECOND
====== ===== ======
1 1 2
2 1 6
3 2 1
4 2 6
5 3 4
6 4 3
7 6 1
8 6 2
I would like to do it in PL/SQL or straight SQL inserts if possible. I did this through Java already using a recursive function to go through the permutations.
You could self join the table:
SELECT ROW_NUMBER() OVER (ORDER BY a.id, b.id) AS pairid,
a.id AS FIRST, b.id AS second
FROM mytable a
JOIN mytable b ON a.groupid = b.groupid AND a.id <> b.id
ORDER BY 1 ASC;

How to select a value with a column name that also needs selected?

The SQL Server 2005 table I'm working from is really strange. Here's a simplified example:
TABLE 1:
key | a | b | c | d | e | f
z 0 1 2 3 4 5 6
y 1 8 9 10 11 12 13
x 14 15 16 17 18 19 20
w 21 22 23 24 25 26 27
TABLE 2:
id | Value
1 a
2 b
3 c
4 e
5 f
What I need to accomplish is to, in a single statement, select the column name from a different table, then get the value here. So it would be something like "Select (select colName from table2 where id=VAR1) From table1 where key = VAR2"
So table2 will return either a/b/c/d/e/f, and then the main statement will get the value of the corresponding value based on the key.
Table2 will always return a-f, and I will know the VAR1 and VAR2 ahead of time.
You can use UNPIVOT:
SELECT [key], val, col
FROM
(SELECT [key], a, b, c, d, e, f
FROM table1
WHERE [key] = #var2) AS src
UNPIVOT
(val FOR col IN
(a, b, c, d, e, f)
)AS unpvt
WHERE col = (SELECT value FROM table2 WHERE id = #var1)
UNPIVOT operation transposes table data from columns to rows creating an extra field where column name is placed. This way you can query table data using the name of the column that is obtained from table2.
Demo here

Finding unique values with multiple columns using certain condition

ID? A B C
--- -- -- --
1 J 1 B
2 J 1 S
3 M 1 B
4 M 1 S
5 M 2 B
6 M 2 S
7 T 1 B
8 T 2 S
9 C 1 B
10 C 1 S
11 C 2 B
12 N 1 S
13 N 2 S
14 N 3 S
15 Q 1 S
16 Q 1 S
17 Z 1 B
I need to find unique values with multiple column with some added condition. The unique value are combination of Col A,B and C.
If Col A has only two rows (like record 1 and 2) and the Column B is same on both data and there is a different value as in Column C then i dont need those records.
If Col A has only multiple rows (like record 3 to 6 ) with different Col B and C combination we want to see those values.
If Col A has multiple rows (like record 7 to 8 ) with different Col B and C combination we want to see those values.
If Col A has only multiple rows (like record 9 to 11 ) with similar/different Col B and C combination we want to see those values.
If Col A has only multiple rows (like record 12onwards ) with similar Col C and similar or different Column B we dont need those values...
If single value like Row 17 there is no need to display either
Tried a lot but not getting exact answer any help is greatly appreciated..
Trying to go through all the logic, I think you want all rows where the values of both columns A and B differ. An easy way to see whether records differ is by looking at the min and max values. And, you can do this using analytic functions:
select A, B, C
from (select t.*,
count(*) over (partition by A) as Acnt,
min(B) over (partition by A) as Bmin,
max(B) over (partition by A) as Bmax,
min(C) over (partition by A) as Cmin,
max(C) over (partition by A) as Cmax
from t
) t
where (Bmin <> Bmax or Cmin <> Cmax)
Your example data does not have any actual duplicates, so I don't think a count(distinct) is necessary. Your rules say nothing about what to do when A only appears once. This version will filter those rows out.