PostgreSQL 9.5 Insert data on a key with multiple occurences - sql

I have 2 tables which are representing the same type of datas, one is in my DB and the other is coming from my client one's. Both his and my table are having some ID as PRIMARY KEY, but they are absolutely not related.
There is a field (field1) which is common between the two table, but this field is not always UNIQUE. In most cases, there are the same amount of tuples with this field in each table, but it is not necessary the case. Here is an example to illustrate the situation :
My table :
id_mytable field1 field2 id_clients
1 aa1 null null
2 aa1 null null
3 aa1 null null
4 aa2 null null
5 aa2 null null
6 aa3 null null
7 aa4 null null
And the client's table:
id_clients field1 field2
9 aa1 value1
10 aa1 value2
11 aa2 value3
12 aa2 value4
13 aa2 value5
14 aa3 value6
15 aa4 value7
And the result I would like to get, sorted by the field1 :
id_mytable field1 field2 id_clients
1 aa1 value1 9
2 aa1 value2 10
3 aa1 null null
4 aa2 value3 11
5 aa2 value4 12
null aa2 value5 13
6 aa3 value6 14
7 aa4 value7 15
You can notice the values not fulfilled in the result table where it was a difference betwenn my and the client's table, and that a new row was inserted. The idea is to be able to fulfill my table with the field2 and the id_clients. So far I cannot figure out a way to achieve that, my guess is that my relative beginner level makes me miss a DB's concept...
And here is an online sample, with the code proposed by ttallierchio : http://rextester.com/LOLH81061
Thank you very much for your attention.

you want to use a full outer join. the reason for this is you are not sure if data exists in either table so you want to combine and take data if exists in either one. i would just use row number to ensure uniqueness.
SELECT row_number() over(order by mt.field1),
coalesce(mt.field1,c.field1) as field1,
coalesce(mt.field2,c.field2) as field2,
c.id as id_clients
FROM mytable mt
FULL OUTER JOIN clients c
on mt.id = c.id and c.field1 = mt.field1;

You can use full outer join. The trick is calculating the new id:
select coalesce(mt.id,
m.maxid + row_number() over (partition by mt.id order by ct.id)
) as newid
mt.field1, ct.field2, ct.id
from mytable mt full outer join
clienttable ct
on mt.id = ct.id and mt.field1 = ct.field1 cross join
(select max(id) as maxid from mytable) as m;

Related

TSQL: Find duplicate values based on two database values

I like to find duplicate entrys based on the same "Article" AND "Warehouse" column. I cant find a solution for an MSSQL-Query to find out the different "Value1" and "Value2" based on the following table:
Article Value1 Value2 Warehouse
123 123 01.01.2021 1
123 456 02.12.2022 1
123 789 05.05.2024 1
123 123 01.01.2021 2
123 123 01.01.2021 3
456 123 01.01.2021 1
456 123 01.01.2021 1
456 123 01.01.2021 1
The result should be:
Article Value1 Value2 Warehouse
123 123 01.01.2021 1
123 456 02.12.2022 1
123 789 05.05.2024 1
EDIT: The Warehouse and Article is always different. In the result I want to the see the same article and warehouse which has different entry's on value1 and value2.
As you can see the article "123" AND Warehouse "1" has different entry´s on the value1 and value2. So I´d like to get them in the result of the SQL-Query.
But the article "456" has the SAME entry's on value1 and value2 for Warehouse 1, so I don´t wan´t them in the result.
Thank you very much for your help!
Use COUNT DISTINCT.
select *
from mytable t1
where exists
(
select null
from mytable t2
where t2.article = t1.article and t2.warehouse = t1.warehouse
having count(distinct value1) > 1 or count(distinct value2) > 1
)
order by article, warehouse, value1, value2;
(This would be more readable with an IN clause in my opinion, but SQL Server doesn't allow IN clauses on tuples like WHERE (article, warehouse) IN (...).)
Use exists:
select t.*
from t
where exists (select 1
from t t2
where t2.article = t.article and
t2.warehouse = t.warehouse and
(t2.value1 <> t.value1 or t2.value2 <> t.value2)
);
It is unclear from your question whether both values have to be different or either value. The above implements either value being different.
For performance, I would recommend an index on (article, warehouse, value1, value2).

SQL Select Return Rows If Column Contain Value or Null Value Base on Key Columns

It was a bit difficult to describe my requirements based on the title, however I'll post with a table sample and result expectation.
I have a table (lets call it TBL_K) that looks like this:
KEY1 KEY2 VALUE1 VALUE2
abc 123 NULL NULL
abc 123 9999 1111
abc 123 9999 1111
ghd 123 NULL NULL
ghd 123 NULL NULL
tiy 134 4444 NULL
tiy 134 4444 NULL
hhh 981 NULL NULL
I want my Select statement to return the result in:
KEY1 KEY2 VALUE1 VALUE2
abc 123 9999 1111
ghd 123 NULL NULL
tiy 134 4444 NULL
hhh 981 NULL NULL
I have came up with own solution with creating two sub-tables with a left outer join but I want to see if there are other ways of creating this result.
It seems nearly to use max() :
select key1, key2, max(val1), max(val2)
from TBL_K tk
group by key1, key2;
SELECT
A.KEY1,
A.KEY2,
B.VALUE1,
B.VALUE2
FROM
(
SELECT
Z.KEY1,
Z.KEY2,
TRIM(Z.VALUE1) VALUE1,
TRIM(Z.VALUE2) VALUE2
FROM
TBL_K Z
WHERE
TRIM(Z.VALUE1) IS NULL
GROUP BY
Z.KEY1,
Z.KEY2,
Z.VALUE1,Z.VALUE2) A LEFT OUTER JOIN
(
SELECT
Y.KEY1,
Y.KEY2,
TRIM(Y.VALUE1) VALUE1,
TRIM(Y.VALUE2) VALUE2
FROM
TBL_K Y
WHERE
TRIM(Y.VALUE1) IS NOT NULL
GROUP BY
Y.KEY1,
Y.KEY2,
Y.VALUE1,Y.VALUE2) B
ON
(A.KEY1 = B.KEY1
AND A.KEY2 = B.KEY2)

SQL Server : retrieve records for a foreign key that don't have common values with another foreign key in the same table

I have a table with the following structure:
Id MemberId Field1 Field2 Data
--------------------------------------------------
1 1 12 abc 1232
2 2 13 asl 234
3 2 12 abc 2345
4 1 3 sd sfsd
5 1 5 45r ffgf
Given parameters member1 and member2, I have to return all id's from member1 that don't have the same values in Field1 and Field2 with member2.
Output example:
member1 = 1
member2 = 2
Expected output:
4
5
Because the the first record and the third record have the same values for Field1 and Field2.
How to achieve this?
I'm using SQL Server 2014.
Edit: I am not allowed to use cursors and temp tables (like #tempTable), I can use only table variables
If I understand correctly, you can use not exists:
select t.*
from t
where not exists (select 1
from t t2
where t2.member1 = t.member1 and
t2.id <> t.id and
(t2.field1 = t.field1 or t2.field2 = t.field2)
);

SQL: Update one field from different table

Let's say I have those two tables:
table1
ID value1 value2
1 NULL NULL
2 NULL NULL
3 NULL NULL
table2
ID value3 value4
5 100 400
6 200 500
7 300 600
I need a SQL-statement to get value3 and value4 of table2 ID 7 into value1 and value2 of table1 ID 1.
How do I go about that?
Thanks
If all you need is to update two fields in a single row, you can do it with subqueries, like this:
update table1
set
value1 = (select value3 from table2 where id=7)
, value2 = (select value4 from table2 where id=7)
where id=1
For updating more fields in related rows of two tables use an UPDATE with JOIN syntax appropriate from your RDBMS.

Problem with joining db tables

I have problem when joining tables (left join)
table1:
id1 amt1
1 100
2 200
3 300
table2:
id2 amt2
1 150
2 250
2 350
my Query:
select id1,amt1,id2,amt2 from table1
left join table2 on table2.id1=table1.id2
My supposed o/p is:
id1 amt1 id2 amt2
row1: 1 100 1 150
row2: 2 200 2 250
row3: 2 200 2 350
I want o/p in row3 as
2 null 2 350
ie I want avoid repetition of data(amt1).
This really is a formatting issue which is best handled by the client. For instance, in SQL*Plus we can use BREAK ....
SQL> select t1.*, t2.* from t1, t2
2 /
A B C D C1
--- --- --- --- ----------
aaa bbb ccc ddd 111
aaa bbb ccc ddd 222
SQL> break on a on b on c on d
SQL> select t1.*, t2.* from t1, t2
2 /
A B C D C1
--- --- --- --- ----------
aaa bbb ccc ddd 111
222
SQL>
Note: in the absence of any further information I opted for a Cartesian product.
edit
BREAK is a SQLPlus command, which suppresses duplicate columns in our rows. It only works in the SQLPlus client. As might be expected, it is covered in Oracle's SQL*Plus User Guide. Find out more.
I used BREAK as an example of the proper way of doing things, because it is clean and correctly implements the separation of concerns. It you are using a different client you would need to use its formatting capabilities. It is possible to tweak the SQL (see below) but that diminishes the utility of the query, because we cannot reuse the query in other places which don't want to suppress the duplicated values.
Anyway, here is one solution which uses the ROW_NUMBER() analytic function in an inline view.
SQL> select * from t1
2 /
A B C D ID
--- --- --- --- ----------
eee fff ggg hhh 1
aaa bbb ccc ddd 2
SQL> select * from t2
2 /
C1 ID
---------- ----------
333 2
111 1
222 2
444 2
SQL> select t1_id
2 , case when rn = 1 then a else null end as a
3 , t2_id
4 , c1
5 from (
6 select t1.id as t1_id
7 , row_number () over (partition by t1.id order by t2.c1) as rn
8 , t1.a
9 , t2.c1
10 , t2.id as t2_id
11 from t1, t2
12 where t1.id = t2.id
13 )
14 order by t1_id, rn
15 /
T1_ID A T2_ID C1
---------- --- ---------- ----------
1 eee 1 111
2 aaa 2 222
2 2 333
2 2 444
SQL>
I chose not to use LAG(), because that only works with fixed offsets, and it seemed likely that the number of rows in T2 would be variable.
Assuning you want all data in a single row, you just do a union select...
Select fieldA from tableA
Union
Select fieldB from TableB
Note that you need to cast the datatype to be the same for both tables.
If you need an other answer, please format the expected result better ;)
Ok...
You have corrected the formating...
In the case above I would simply return 2 cursors from my query. The example data provides no field to link both tables together, so i see no way to join them in a resonable manner. It is possible for a sproc to return several resultsets.
You've done the cartesian product of the two tables since you haven't specified any join criteria. In order to eliminate duplicates, you need to specify how you want the tables to join.
For example, you could try
select * from table1, table2 where table2.val = 111;
Your example doesn't have any join key, so there's no obvious value to join the tables on. But is a more typical example, there would be a related value in both tables so that you could join them together in a meaningful way.
You seem to be doing a cross join here. I suspect you wanted either an equi join or a left outer join.