I was wondering if there was a way to convert a self subquery to a self join
Here is the self subquery
SELECT a,
b
FROM c AS t1
WHERE ( b IN (SELECT b
FROM c AS t2
WHERE ( t1.b = b )
AND ( t1.e <> e )) )
If you only want to find the duplicates an EXIST would probably be faster:
SELECT a,b FROM c WHERE EXISTS(SELECT NULL FROM c c2 WHERE c2.b=c.b AND c2.e<>c.e)
If you want to join every record with its duplicate but get only one record for each:
select t1.a
, t1.b
, t1.e as t1e
, t2.e as t2e
from c as t1
inner join c as t2
on t1.b = t2.b
and t1.e > t2.e
(note that i've used > instead of <>)
As e is the Primary Key another way of approaching this would be
SELECT a,
b
FROM (SELECT a,
b,
COUNT(*) OVER (PARTITION BY b) AS Cnt
FROM c) T1
WHERE Cnt > 1
SELECT t1.a, t2.b
FROM c as t1
join c as t2 on t1.b=t2.b
WHERE t1.e <> t2.e
select t1.a
, t1.b
from c as t1
join c as t2
on t1.b = t2.b
and t1.e <> t2.e
Related
I am new to sql and have a simple question. I have two tables, t1 and t2, both have same fields A, B, C,D
I want to create a sql that
select
*
from t1
where (t1.A exist in t2.A)
AND (combination (ABC) from t1 not exist in t2)
I am using access 2013
Thank you!
You may try using exists logic:
SELECT t1.*
FROM table1 t1
WHERE
EXISTS (SELECT 1 FROM table2 t2 WHERE t2.A = t1.A) AND
NOT EXISTS (SELECT 1 FROM table2 t2 WHERE t2.B = t1.B AND t2.C = t1.C);
Something like this may work:
SELECT *
FROM t1
WHERE
A in (SELECT A from t2) AND
NOT EXISTS (
SELECT *
FROM t2
WHERE t1.B = t2.B AND
t1.C = t2.C AND
t1.D = t2.D
);
I am having an issue in extracting data using data of two tables in SQL.
select A, B, C, D
from Table_one T1
where A in (select T2.A from Table_two T2
where T2.E <> 'ZZZ');
This returns A, B, C, D where E in T2 is not ZZZ.
However, when I add another where clause like below,
it returns data where T2 is ZZZ also.
select A, B, C, D
from Table_one T1
where A in (select T2.A from Table_two T2
where T2.E <> 'ZZZ')
and D <> 0 ;
This ignores "T2.E <> 'ZZZ'" part, but "D<>0" is not ignored.
Why is this happening?
Because you have duplicates in Table_two. For some of those duplicates, one has the value of ZZZ and the other does not.
You are using the wrong logic if you want to exclude rows that have a ZZZ in table_two. I would recommend NOT EXISTS:
select A, B, C, D
from Table_one T1
where not exists (select 1
from Table_two T2
where T1.A = T2.A and
T2.E = 'ZZZ'
) and
D <> 0 ;
I have a group of insert statements below. The only difference between them is the Thru_DT. The first insert is for 6/30/2019 date. The second is for 15 days before that date and the third is for 15 days before the second insert's date. How do I generate these dates automatically without having to hard code them?
INSERT INTO table1 (a, b, c)
SELECT t2.a1, Max(t2.b1) Provider, t2.c1
From table2 t2
LEFT JOIN tb t1 On t2.a = t1.a1
WHERE t1.b Is Null And t2.Thru_DT >= '6/30/2019'
And t2.c In (Select CCN From table3)
INSERT INTO table1 (a, b, c)
SELECT t2.a1, Max(t2.b1) Provider, t2.c1
From table2 t2
LEFT JOIN tb t1 On t2.a = t1.a1
WHERE t1.b Is Null And t2.Thru_DT >= '6/15/2019'
And t2.c In (Select CCN From table3)
INSERT INTO table1 (a, b, c)
SELECT t2.a1, Max(t2.b1) Provider, t2.c1
From table2 t2
LEFT JOIN tb t1 On t2.a = t1.a1
WHERE t1.b Is Null And t2.Thru_DT >= '6/1/2019'
And t2.c In (Select CCN From table3)
You can build the dates in a CTE:
;WITH cte_date(thru_DT)
AS
(
SELECT #GivenDate
UNION ALL SELECT DATEADD(DAY,-15,#GivenDate)
UNION ALL SELECT DATEADD(DAY,-30,#GivenDate)
)
INSERT INTO table1 (a, b, c)
SELECT t2.a1, Max(t2.b1) Provider, t2.c1
From table2 t2
INNER JOIN table3 t3
ON t2.c=t3.CCN
INNER JOIN cte_date d
ON t2.Thru_DT >= d.Thru_DT
LEFT JOIN tb t1 On t2.a = t1.a1
WHERE t1.b Is Null
Use a table constructor:
INSERT INTO table1 (a, b, c)
SELECT t2.a1, Max(t2.b1) Provider, t2.c1
FROM table2 t2 LEFT JOIN
tb t1
ON t2.a = t1.a1 CROSS JOIN
(VALUES ('2019-06-30'), ('2019-06-15'), ('2019-06-01')
) v(Thru_DT)
WHERE t1.b Is Null AND
t2.Thru_DT >= v.Thru_DT AND
t2.c IN (SELECT CCN FROM table3);
I have two tables, tbl and tbl2 I have to join. Columns of tbl are irrelevant. Here is the tructure of tbl2:
CREATE TABLE tbl2 (
a VARCHAR(10)
, b VARCHAR(10)
, c VARCHAR(10)
, d VARCHAR(10)
, e VARCHAR(10)
);
What I need to do is apply the following join:
if there are several rows with the same a, b and c LEFT JOIN them on a, b, c and d.
else if there are several rows with the same a and b and they are not in the set mentioned above LEFT JOIN on a, b and c
else LEFT JOIN remaining rows from tbl2 on a and b.
I have been thinking what is the best way to achieve the following. tbl2 can be modified since it is only used for the purpose of this query.
Do you have any ideas what is the most efficient way of achieving this?
EDIT:
By 'having the same a, b and c' I meant something like this:
SELECT a, b, c FROM tbl2 GROUP BY a, b ,c HAVING COUNT(*) > 1
WITH tab_a AS
(
SELECT t2.a
, t2.b
, t2.c
, t2.d
, t2.e
, CASE WHEN t1.c = t2.c THEN 1 ELSE 0 END +
CASE WHEN t1.d = t2.d THEN 1 ELSE 0 END AS other_two
FROM tbl t1
LEFT JOIN tbl2 t2
ON t1.a = t2.a
AND t1.b = t2.b
)
SELECT a
, b
, c
, d
, e
FROM tab_a
WHERE other_two = (SELECT MAX(other_two) FROM tab_a);
put these three queries in if else condition. If you want them all then UNION these three.
select *
from tbl t1 left outer join tbl2 t2
on (t1.a=t2.a and t1.b=t2.b and t1.c=t2.c and t1.d=t2.d)
where t2.a=t2.b and t2.b=t2.c;
select *
from tbl t1 left outer join tbl2 t2
on (t1.a=t2.a and t1.b=t2.b and t1.c=t2.c )
where t2.a=t2.b and t2.b<>t2.c;
select *
from tbl t1 left outer join tbl2 t2
on (t1.a=t2.a and t1.b=t2.b)
where t2.a<>t2.b and t2.b<>t2.c;
or try this:
select *
from tbl t1 left outer join tbl2 t2
on (
(t1.a=t2.a and t1.b=t2.b and t1.c=t2.c and t1.d=t2.d and t2.a=t2.b and t2.b=t2.c)
or
(t1.a=t2.a and t1.b=t2.b and t1.c=t2.c and t2.a=t2.b and t2.b<>t2.c)
or
(t1.a=t2.a and t1.b=t2.b and t2.a<>t2.b and t2.b<>t2.c) );
I want to get the top 1 row for each unique value of b with the minimum value of c for that particular value of b. Even though there can be more than 1 row with the same min value (just chose the first one)
myTable
a integer (unique)
b integer
c integer
I've tried this query
SELECT t1.*
FROM myTable t1,
(SELECT b,
MIN(c) as c
FROM myTable
GROUP BY b) t2
WHERE t1.b = t2.b
AND t1.c = t2.c
However, in this table it's possible for there to be more than 1 instance of the minimum value of c for a given value of b. The above query generates duplicates under these conditions.
I've got a feeling that I need to use rownum somewhere, but I'm not quite sure where.
You can use ROW_NUMBER:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY b ORDER BY c) AS rn
FROM myTable
) AS T1
WHERE rn = 1
To tie-break between the equal c's, you will need to subquery one level further to get the min-a for each group of equal c's per b. (A mouthful!)
select t0.*
FROM myTable t0
inner join (
select t1.b, t1.c, MIN(a) as a
from myTable t1
inner join (
select b, min(c) as c
from myTable
group by b
) t2 on t1.b = t2.b and t1.c = t2.c
group by t1.b, t1.c
) t3 on t3.a = t0.a and t3.b = t0.b and t3.c = t0.c