Multiple NOT distinct - sql

I've got an MS access database and I would need to create an SQL query that allows me to select all the not distinct entries in one column while still keeping all the values.
In this case more than ever an example is worth thousands of words:
Table:
A B C
1 x q
2 y w
3 y e
4 z r
5 z t
6 z y
SQL magic
Result:
B C
y w
y e
z r
z t
z y
Basically it removes all unique values of column B but keeps the multiple rows of the
data kept. I can "group by b" and then "count>1" to get the not distinct but the result will only list one row of B not the 2 or more that I need.
Any help?
Thanks.

Select B, C
From Table
Where B In
(Select B From Table
Group By B
Having Count(*) > 1)

Another way of returning the results you want would be this:
select *
from
my_table
where
B in
(select B from my_table group by B having count(*) > 1)

select
*
from
my_table t1,
my_table t2
where
t1.B = t2.B
and
t1.C != t2.C
-- apparently you need to use <> instead of != in Access
-- Thanks, Dave!
Something like that?

join the unique values of B you determined with group by b and count > 1 back to the original table to retrieve the C values from the table.

Related

How to fill in missing rows in a table with default values in sqlite

I have a table with 3 columns (a, b, c) and I want to make sure that for each possible combination of values in the first two columns, there is a row containing that combination. For example if this is my table:
a b c
--- --- ---
P X 1
Q Y 2
Q Z 3
R Y 4
S Y 5
S Z 6
The unique values in column a are P, Q, R, S, and the unique values in column b are X, Y, Z. So I want to create a query that returns 12 rows (4×3) that fills in missing values in column c with a default value like 0, for example:
a b c
--- --- ---
P X 1
P Y 0
P Z 0
Q X 0
Q Y 2
Q Z 3
R X 0
R Y 4
R Z 0
S X 0
S Y 5
S Z 6
The way I'm currently doing it is this:
select a, b, ifnull(c, 0)
from (select distinct a from table),
(select distinct b from table)
left join table using (a, b)
Unfortunately, this query is very slow since the table contains like ten thousand rows. If I precompute the query and store it in a table, then accessing the results is faster, but it takes a lot of space, most of which is probably just filled with zeros in the c column. Is there any way to make this query faster?
For this query:
select a.a, b.b, coalesce(c.c, 0)
from (select distinct a from table) a cross join
(select distinct b from table) b left join
table c
using (a, b);
You want indexes on:
(a, b)
(b)
The first index can be used for the select distinct a and for the join. The second can be used for the select distinct b.

I have 3 columns [A, B, C] in my SQL table. I want to find table entries, where values in A is same, in B is same, but C is different

I have 3 columns [A, B, C] in my SQL table. I want to find table entries, where values in A is same, in B is same, but C is different.
A B C
1 2 3
4 5 6
*3 4 5*
*3 4 6*
*7 8 9*
6 1 2
*7 8 3*
I want to preferably get something like:
A B C
3 4 5
3 4 6
7 8 9
7 8 3
as my result.
Thanks :)
The core of the solution below is to aggregate over your table on both columns A and B, and then retain those groups having more than one C value. Then join your full table to this aggregation query to retain only the records you want.
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT A, B
FROM yourTable
GROUP BY A, B
HAVING COUNT(DISTINCT C) > 1
) t2
ON t1.A = t2.A AND t1.B = t2.B
ORDER BY
t1.A, t1.B;
Here is a demo in MySQL, though the above query should run on pretty much any other database with little modification.
Demo
Try this:
select A,B,C from (
select A,B,C, avg(C * 1.0) over (partition by A,B) [avg] from MY_TABLE
) a where [avg] <> C
The idea behind is simple, if all numbers within a set are equal, they also are equal to the average of the set.
This one should work too:
SELECT DISTINCT
t1.*
FROM
test t1
INNER JOIN
test t2 ON t2.a = t1.a
AND t2.b = t1.b
AND t2.c <> t1.c;
Here's a demo: link
I'm not sure about performance due to lots of duplicates being generated/truncated compared to other solutions, though.
No need to count or rank; you only want to check if at least one qualifying row EXISTS
select *
from thetable tt
where exists(
select * from thetable x
where x.a = tt.a and x.b = tt.b
and x.c <> tt.c
);

Suppress rows with reverse/swapped values

I would like to query a database table that contains rows that have reverse values than other rows. So the table looks like this
Src Trgt ValueA ValueB
A B 1,44 5
B A 1,44 5 <--
C D 1,23 8
D C 1,23 8 <--
F G 5,12 9
G F 5,12 9 <--
What I want is a query that returns all rows that do not again with the source and target value swapped. The rows that should not be queried are the ones that have the same Value A and B like another row, but only with source and target value swapped (The ones marked in above table)
So, the desired results would look like this:
Src Trgt ValueA ValueB
A B 1,44 5
C D 1,23 8
F G 5,12 9
I think this is what you want:
select t.*
from t
where t.src < t.trgt
union all
select t.*
from t
where t.src > t.trgt and
not exists (select 1
from t t2
where t2.src = t.trgt and t2.trgt = t.src and
t2.a = t.a and t2.b = t.b
);
It keeps the first row encountered, filtering out equivalent rows where the first two columns are switched.
EDIT:
Another approach if you just one one row per combo is:
select least(src, trgt) as src, greatest(src, trgt) as trgt, a, b
from t
group by least(src, trgt), greatest(src, trgt), a, b;
This runs the risk of returning a row not in the original data (if the row has no duplicate and trgt > src.
SELECT *
FROM ztable zt
WHERE zt.source < zt.target -- pick only one of the twins
OR NOT EXISTS( -- OR :if it is NOT part of a twin
SELECT *
FROM ztable nx
WHERE nx.source = zt.target
AND nx.target = zt.source
);
Assuming that rows with source=target are not present or not wanted.

How to insert same records from one table to another table 4 to 5 times randomly

table 1 is my current table. newtable is what needs to be insert into.
Here's the example:
Table 1
a
b
c
d
newTable
a
a
a
a
b
b
b
b
b
c
c
c
c
c
d
d
d
d
Try this in Oracle:
SELECT x, LEVEL from myTable t
CONNECT BY LEVEL <= ROUND(DBMS_RANDOM.VALUE (4, 5))
and prior x = x
and prior sys_guid() is not null;
If you are using mysql;
select * from table order by rand() limit 3
then
Insert it into new new table
Do it many times as you want.
You can follow previous post
Thank You,
Sameera

Help required with a complex self join sql query

myTable is having composite key formed of columns A and B (total columns A, B, C, D, E).
I want to exclude/ignore records where value of D (say order number) is same and E (say decision) is Y in one but N or Null in other. (means all the twin-records with same order number (equal D value) which were ordered first (so E=Y) and then again cancelled (so E=N) should be ignored)
So I pulled out A,B for all records where D is same but E is Y in one and N in other
SELECT *
FROM myTable A, myTable B
WHERE
(A.D=B.D)
AND
((A.E ='Y' AND (B.E ='N' OR B.E IS NULL)) OR (B.E='Y' AND (A.E='N' OR A.E IS NULL)))
Now my final output should be all records from myTable but not the records found above.
I wrote a join query but its not working as it should. Basically issue is how to compare two composite keys ??
Sample Data:
A B C D E
=========================
1 A xyz ONE Y
2 B pqr TWO Y
3 C lmn ONE N
4 D abc THREE Y
5 E ijk FOUR Y
=========================
Thus, my output should be records 2,4 and 5. As 1 and 3 will be ignored. Because 1.D = 3.D and 1.E is Y but 3.E is N.
Thanks,
Nik
I want to exclude records where value of D is "XYZ".
Why not simply query like this directly?
select *
from myTable
where D <> 'XYZ'
To exclude rows from Temp, you could:
select *
from myTable
where not exists
(
select *
from temp
where myTable.A = temp.A
and myTable.B = temp.B
)
Or with an exclusive left join:
select *
from myTable
left join
temp
on myTable.A = temp.A
and myTable.B = temp.B
where temp.A is null
If I've correctly understood you, what you need is this:
select x.*
from mytable x left outer join
( select mt1.a, mt1.b
from mytable mt1 inner join
mytable mt2 on mt1.d = mt2.d
where ((mt1.E ='Y' AND (mt2.E ='N' OR mt2.E IS NULL)) OR (mt2.E='Y' AND (mt1.E='N' OR mt1.E IS NULL)))
) y on x.a = y.a and x.b = y.b
where y.a is NULL
You need something like
select A.*
from myTable A
WHERE (SELECT COUNT(*) FROM myTable B WHERE B.D = A.D AND (B.E IS NULL OR B.E = 'N')) = 0