In my procedure I have two tables with the same data. I go through my first table through a cursor. Which compares with the second table that I find much the same data. What if, for example in my table_1 I have ten in my data and I have 12 data table2 how to detect missing data in my two table_1 which is traversed by the cursor?
Thx.
Sounds very much like you'd be better off using the MINUS operator.
SELECT a, b, c
FROM table1
MINUS
SELECT a, b, c
FROM table2
This will show you all results that exist in table1 which are not present in table2. In order to show discrepancies both ways, you could do something like this:
SELECT z.*, 'In table1, not in table2' problem_description
FROM (
SELECT a, b, c
FROM table1
MINUS
SELECT a, b, c
FROM table2
) z
UNION ALL
SELECT z.*, 'In table2, not in table1' problem_description
FROM (
SELECT a, b, c
FROM table2
MINUS
SELECT a, b, c
FROM table1
) z
SQL Fiddle for this answer
Related
I have two tables A and B.
Both the tables have same number of columns.
Table A always contains all ids of Table B.
Need to fetch row from Table B first if it does not exist then have
to fetch from Table A.
I was trying to dynamically do this
select
CASE
WHEN b.id is null THEN
a.*
ELSE
b.*
END
from A a
left join B b on b.id = a.id
I think this syntax is not correct.
Can some one suggest how to proceed.
It looks like you want to select all columns from table A except when a matching ID exists in table B. In that case you want to select all columns from table B.
That can be done with this query as long as the number and types of columns in both tables are compatible:
select * from a where not exists (select 1 from b where b.id = a.id)
union all
select * from b
If the number, types, or order of columns differs you will need to explicitly specify the columns to return in each sub query.
So I have three tables (A, B, C). In tables A and B I have points, and I want to insert into C each row from A, and some columns from the closest point from B to each point in A, as well as the distance between them. I know that the query to get the nearest neighbour is this:
SELECT DISTINCT ON (A.id5) A.state, B.way, st_distance (A.geom,B.geom) INTO C
FROM A, B
WHERE ST_DWithin(A.geom, B.geom, 150)
ORDER BY A.objectid, ST_Distance(A.geom,A.geom)
But I need to get that into a bigger INSERT query, and I tried to do it this way:
INSERT INTO complete(id_door, distance, id_way,Y, X, geom, check)
(SELECT A.state, (select distinct on (A.id5) ST_DISTANCE(A.geom,B.geom) from A order by A.id5, st_distance(A.geom,B.geom)), b.way, ST_Y(B.geom), ST_X(B.geom) ,B.geom, V.check
FROM A, B, C, V
WHERE
ST_INTERSECTS(A.geom, V.geom)\
AND ST_DWithin(A.geom, B.geom,150))
But this is not the right way, because I get the error:
psycopg2.ProgrammingError: more than one row returned by a subquery used as an expression
I cannot copy all the distances from A and B to C and then delete all but the closest because it is a huge table and I would run out of memory, so I need a way to only insert the rows with the info from the closest point from B to A.
What am I doing wrong here? Thank you in advance
UPDATE:
After some help, I have learned that I should use a Lateral in the Select query, but I'm not sure how to use it.
I need the Select to get each row in table A and find its nearest neighbour from table B, which I guess it is done using the query previously stated, and insert into table C some columns from A, some columns from its nearest neighbour (table B), and some columns from table V, which is selected by an Intersect condition. The main problem is how to organize all that into the Select so I don't get an error.
This is where I am at this point:
INSERT INTO C (id_door, distance, id_way,Y, X, geom, check)
(SELECT A.state, l.*, V.check
FROM A, B, C, V
lateral (select st_distance(a.geom,b.geom), b.way, ST_Y(B.geom), ST_X(B.geom) ,B.geom
From B
Where ST_DWithin(a.geom, b.geom,150))
Order by a.geom<->b.geom limit 1) l
WHERE
ST_INTERSECTS(A.geom, V.geom)
You can use lateral join - very smart type of subquery that can reference tables outside the subquery. More about lateral you can find here
-- Edited according to new information in answer --
Insert into C (id_door, distance, id_way,Y, X, geom, check)
select l.*
from a,
lateral (select a.state, st_distance(a.geom,b.geom),
b.way, ST_Y(B.geom), ST_X(B.geom), B.geom,
v.check
from b, v
where ST_DWithin(a.geom, b.geom,150)
and st_dwithin(a.geom,v.geom,0)
and st_intersects(a.geom,v.geom)
order by a.geom<->b.geom, v.geom limit 1) l
If you want more records per each point from A then increase the limit from 1 to your desired value.
I have a query like this:
Select * from
(Select a, b, c from table1 where some condition) as Result1,
(Select d, e from table2 where some another condition) as Result2
everything is OK until one of the nested selects returns nothing, then another select returns nothing too in finally select.
please tell me what is wrong with me?
As per my comment above, the following should work how you expect:
select
*
from
(select a, b, c from table1 where predicate1) Result1
full outer join
(select d, e from table2 where predicate2) Result2 on
1 = 1
Try:
Select (
(Select a, b, c from table1 where some condition) as Result1,
(Select d, e from table2 where some another condition) as Result
)
Try an inner or self join
Post some result samples to get a better understanding of the issue.
In postgresql I got 4 tables
Table A:
-----------
a_id
a_date
Table B
-----------
a_id b_id
Table C:
-------------------
c_id
b_id
invoice_number
Table D
-------------------
d_id
invoice_number
value_D
Multiple records have value_D
I would like to select Table A, Table B, Table C and Table D, where a_date BETWEEN X AND Y.
However, I would also like to select all the other value_D that are not included in my selection (so A innerjoin B innerjoin C full outerjoin D)
my code
SELECT
Table A, Table B, Table C, Table D
FROM
Table A
JOIN
Table B ON A.a_id = B.a_id
JOIN
Table C ON B.b_id = C.b_id
FULL OUTER JOIN
Table D ON C.invoice_number = D.invoice_number
WHERE
A.a_date BETWEEN X AND Y;
It only shows D.value_d for the A.a_id, where A.a_date BETWEEN X and Y.
I would like however that D.value_d would also be shown for A.a_id, where A.a_date is also other.
I am kinda a newbie, so hopefully it is understandable and you could help me.
Thanks in advance
You can also add more conditions to the Where clause, for example:
"a_date BETWEEN X AND Y OR a_date > '2015-04-21'". This will retrieve the union of both conditions.
Regards
I think I solved it.
SELECT Table A, Table B, Table C, Table D
FROM Table A
JOIN Table B ON A.a_id = B.a_id
JOIN Table C ON B.b_id = C.b_id
JOIN Table D ON C.invoice_number = D.invoice_number
WHERE A.a_date BETWEEN X AND Y OR
D.value_D IN (SELECT D.value_D
FROM Table D
JOIN Table C ON D.invoice_number on C.invoice_number
JOIN Table B ON C.b_id = B.b_id
JOIN Table A ON B.a_id = A.a_id
WHERE A.a_date BETWEEN X AND Y);
Thank you all for the help guys!
I have a Table which has 2 fields say A,B. Suppose A has values a1,a2.
Corresponding records for a1 in B are 1,2,3,x,y,z.
Corresponding records for a2 in B are 1,2,3,4,d,e,f
I need a a query to be written in DB2, so that it will fetch the common records in B for each record in A (a1 and a2).
So here the output would be :
A B
a1 1
a1 2
a1 3
a2 1
a2 2
a2 3
Can someone please help on this?
Try something like:
SELECT A, B
FROM Table t1
WHERE (SELECT COUNT(*) FROM Table t2 WHERE t2.B = t1.B)
= (SELECT COUNT(DISTINCT t3.A) FROM Table t3)
ORDER BY A, B
This might not be 100% accurate as I can't test it out in DB2 so you might have to tweak the query a little bit to make it work.
with t(num) as (select count(distinct A) from table)
select t1.A, t1.B
from table t1, table t2, t
where t1.B = t2.B
group by t1.A, t1.B, num
having count(*) = num
Basically, the idea is to join the same table with column B and filter out just the ones that match exactly the same number of times as the number of elements in column A, which indicates that it is a common record out of all the A values.