Get Records with both matching values in SQL - sql

Table A
id1 | id2 |
---------------
2 | 3 |
4 | 5 |
Table B
groupid | parentid | uid
----------------
4 | 2 (id1) | 1
4 | 3 (id2) | 2
6 | 2 | 3
7 | 4 (Id1) | 4
8 | 4 (Id1) | 5
8 | 5 (Id2) | 6
8 | 6 | 7
I want to fetch records where groupid should have both id1 & id2.
So in this case uid 1,2 & 5,6 should be retrieved because groupid 4 & 8 have both of them.
How to achieve this in SQL? By SQL, let's say SQL Server

This should do the job for you:
select distinct B1.uid from TableB B1
join TableB B2 on B1.groupid = B2.groupid and B1.parentid ! = B2.parentid
and (
(B1.parentid in (select id1 from TableA) AND B2.parentid in (select id2 from TableA))
OR
(B2.parentid in (select id1 from TableA) AND B1.parentid in (select id2 from TableA))
)
Test it here:
http://rextester.com/KZY45975

Try this query
select b.uid from TableB b inner join TableA a on (a.id1 = b.parentid) inner join TableB c on (c.parentid = a.id2 and c.uid = b.uid)
might returns what you want

Related

Problem with creating a Procedure which should filter data

I need to create a procedure which filters data and insert it to a table.
I have 4 tables: (the keys are the id's)
table1:
id1
parameter1
parameter2
parameter3
table2:
id1
id2
table3:
id2
id3
value1
value2
value3
table4:
id2
id3
value1
value2
value3
I need to create a procedure which inserts to table 4 the values from table 3: value1, value2, value3, only if they are smaller than or equal to the parameters from table 1 (parameter1, parameter2, parameter3)
I've tried the next thing:
insert into table4 (
,Id2
,Id3
,value1
,value2
,value3
)
select
,Id2
,Id3
,value1
,value2
,value3
FROM table1
LEFT JOIN table2 ON table1.id1 = table2.id1
LEFT JOIN table3 ON table2.id2 = table3.id3
WHERE table3.value1 <= table1.parameter1
and table3.value2 <= table1.parameter2
and table3.value3 <= table1.parameter3
But each run, 3 new rows are inserted to table4 with different values and wrong values (they are bigger than the parameters).
What am I doing wrong? Should I create the procedure with IF statement instead? How to make it right?
I've added an example.
As you can see, the new table: table 4, has only 2 rows, because the value of 'value 2' in table3 (value 2= 12) is greater than 'parameter2' (parameter2= 11) (from table 1)
table1:
Id1 | Parameter1 | Parameter2 | Parameter3 |
=====+============+=============+============+
1 | 1 | 2 | 3 |
2 | 10 | ** 11 ** | 12 |
3 | 10 | 15 | 16 |
table2:
Id1 | Id2 |
=====+=====+
1 | 4 |
2 | 5 |
3 | 6 |
table3:
Id2 | Id3 | Value1| Value2| Value3|
=====+=====+========+=======+=======+
4 | 7 | 1 | 2 | 3 |
5 | 8 | 10 |** 12**| 12 |
6 | 9 | 1 | 2 | 3 |
The new table (table 4) should be:
table4:
Id2 | Id3 | Value1| Value2| Value3|
=====+=====+========+=======+=======+
4 | 7 | 1 | 2 | 3 |
6 | 9 | 1 | 2 | 3 |
If you use table3 as the table you select from, you can use joins with the other tables as filters when inserting. Try this (for SQL Server):
INSERT INTO table4 (
id2
,id3
,value1
,value2
,value3
)
SELECT
t3.id2
,t3.id3
,t3.value1
,t3.value2
,t3.value3
FROM table3 t3
JOIN table2 t2 on t3.id2 = t2.id2
JOIN table1 t1 on t2.id1 = t1.id
and t3.value1 <= t1.parameter1
and t3.value2 <= t1.parameter2
and t3.value3 <= t1.parameter3

Query for unique values

I have the following database table in Access:
Field1 | Field2
A | 1
B | 1
C | 2
D | 2
B | 3
O | 3
L | 3
I want to develop a query in Access (preferably without using SQL) to select all values in Field2 corresponding to an occurence of the value "B" in field 1. This query should yield
Field1|Field2
A | 1
B | 1
B | 3
O | 3
L | 3
Use a subquery:
select t.*
from t
where t.field2 in (select t2.field2 from t as t2 where t2.field1 = 'B');

Remove duplicates from inner join with one table

I have following table
id | cId
---------------
1 | 1
2 | 1
3 | 2
4 | 2
I need help with query, that return following result
id1 | id2 | cId
----------------------
1 | 2 | 1
3 | 4 | 2
SELECT s1.id firstC, s2.id secondC
FROM SingleTable s1 inner join SingleTable s2 on s1.cId = s2.cId
But i get duplicates. I want gte result without duplicates.
My result:
id1 | id2 | cId
---------------
1 | 1 | 1
2 | 1 | 1
1 | 2 | 1
2 | 2 | 1
3 | 3 | 2
4 | 3 | 2
3 | 4 | 2
4 | 4 | 2
Please help.
You can just group by the cId and then select the highest and lowest id for every cId
SELECT cId,
min(id) as id1,
max(id) as id2
FROM SingleTable
GROUP BY cId
Remove the duplicates (s1.id = s2.id) with an extra condition (s1.id < s2.id):
SELECT s1.id firstC, s2.id secondC
FROM SingleTable s1 INNER JOIN SingleTable s2
ON (s1.cId = s2.cId AND s1.id < s2.id)

PostgreSQL Table Overlap Count

I am using postgresql.
I have a table that looks like this
| id1 | id2 |
------------------------------------
| 1 | 6 |
| 1 | 12 |
| 2 | 6 |
| 3 | 1 |
| 3 | 2 |
| 2 | 2 |
I am trying to design a query that given for example: id1=1, it will return all id1's with their overlap in id2 in relation to the given id1. Do not include the given id1 in the results.
For example, if it were given id1=1, the result should be:
| id1 | num_occurences |
------------------------------------
| 2 | 1 |
| 3 | 0 |
An id1 of 2 would return 1 because id1=1 and id1=2 have only id2=6 in common. id1 of 3 returns 0 because there is no overlap in occurrences.
I think I might want to use an INNER JOIN but I am not sure.
Any suggestions?
Since you also want zero results, you could use a LEFT JOIN to check the condition;
SELECT a.id1, COUNT(b.id1) num_occurences
FROM mytable a
LEFT JOIN mytable b ON a.id2 = b.id2 AND b.id1 = [id]
WHERE a.id1 <> [id]
GROUP BY a.id1
...where in your case, [id]=1.
What it does is check for each row in "b" (with id1=1) check if there's a row in "a" with the same id2 and an id1 <> 1. Then all it needs to do is group and count the results.
An SQLfiddle to test with.
SELECT id1, SUM( CASE
WHEN id1=id2 THEN 1
ELSE 0
END )
AS num_occurences
FROM table
GROUP by id1
Not a single JOIN was given that day.

Using CASE for a specific situation - How TO

I'm trying to find the proper SQL for the following situation:
Supposed we have two tables:
TABLE A
ID int,
TEXT varchar(200)
TABLE B
ID int,
A_NO int,
B_NO int
Fields named "ID" on both tables can be join to link tables.
The following SQL:
SELECT
A.ID,
B.A_NO,
B.B_NO
FROM
A
LEFT JOIN
B
ON A.ID = B.ID
ORDER BY A.ID, B.A_NO, B.B_NO
gives the following results:
Now, the problem.
What is asked for is to have in the column B_NO a value = 1 for the MIN value of column A_NO and a value = 0 for all the others row with the same A_NO value.
The results below are expected:
Please note that, in this example, we can find two rows for each B_NO value but it is possible to have more than 2 rows.
I have tried to reproduce these results by using a CASE but with no success.
Thanks for you help in advance,
Bouzouki.
Try this using CTE and ROW_NUMBER(); (DEMO)
Please note: I have considered myT as your joined query of A and B tables for demo purpose. So replace myT with as yours A LEFT JOIN B ON A.ID = B.ID.
;with cte as (
select id, a_no, b_no,
row_number() over(partition by id,b_no order by a_no) rn
from myT
)
select id,a_no, case when rn=1 then b_no else 0 end b_no
from cte
order by a_no
--RESULTS FROM DEMO TABLE
| ID | A_NO | B_NO |
-------------------------
| 1031014 | 1 | 1 |
| 1031014 | 2 | 0 |
| 1031014 | 3 | 2 |
| 1031014 | 4 | 0 |
| 1031014 | 5 | 3 |
| 1031014 | 6 | 0 |
| 1031014 | 7 | 4 |
| 1031014 | 8 | 0 |
| 1031014 | 9 | 5 |
| 1031014 | 10 | 0 |
something like
select ID, a_no, b_no,
case when a_no = min_a_no then b_no else 0 end as new_b_no
from
a left join b on a.id = b.id left join
(Select ID, B_no, min(a_no) as min_a_no
from a left join b on a.id = b.id
group by id, b_no) m on a.id = m.id and b.b_no = m.b_no
ORDER BY A.ID, B.A_NO