Select non distinct rows from two columns - sql

My question is very similar to Multiple NOT distinct only it deals with multiple columns instead of one. I have a table like so:
A B C
1 1 0
1 2 1
2 1 2
2 1 3
2 2 4
2 3 5
2 3 6
3 1 7
3 3 8
3 1 9
And the result should be:
A B C
2 1 2
2 1 3
2 3 5
2 3 6
3 1 7
3 1 9
Essentially, like the above question, removing all unique entries only where uniqueness is determined by two columns instead of one. I already tried various tweaks to the above answer but couldn't get any of them to work.

You are using SQL Server, so this is easier than in Access:
select A, B, C
from (select t.*, count(*) over (partition by A, B) as cnt
from t
) t
where cnt > 1;
This use of count(*) is as a window function. It is counting the number of rows with the same value of A and B. The final where just selects the rows that have more than one entry.

Another possible solution with EXISTS
SELECT a, b, c
FROM Table1 t
WHERE EXISTS
(
SELECT 1
FROM Table1
WHERE a = t.a
AND b = t.b
AND c <> t.c
)
It should be fast enough.
Output:
| A | B | C |
-------------
| 2 | 1 | 2 |
| 2 | 1 | 3 |
| 2 | 3 | 5 |
| 2 | 3 | 6 |
| 3 | 1 | 7 |
| 3 | 1 | 9 |
Here is SQLFiddle demo

Related

Select rows with a column equal to 1 OR those that are referenced in an other table

I have 2 tables A and B, as so:
A: B:
A_id | Val B_id | A_id
------------ ------------
1 | 1 1 | 1
2 | 1 2 | 1
3 | 2 3 | 2
4 | 1 4 | 2
5 | 3 5 | 5
6 | 1
I would like to select rows from A where Val = 1 OR those that are referenced in B.
So for this particular example, the select would retrieve:
A_id | Val
----------
1 | 1
2 | 1
4 | 1
5 | 3
Note that row 4 is not referenced in table B, but Val is equal to one, and Val from row 5 is != 1 but the row is referenced in table B.
I tried using the DISTINCT keyword but the problem is that it doesn't select row 4 because it is not referenced in table B.
Thanks for your help.
You can use EXISTS:
SELECT A.*
FROM A
WHERE A.Val = 1
OR EXISTS (SELECT 1 FROM B WHERE B.A_id = A.A_id);

Extract all rows of a column based on the value of another column (SQL query)

I have table
a | b
-----
1 | 3
3 | 2
3 | 4
2 | 5
3 | 6
2 | 7
how to write sql query if a = 1 then result 3 2 4 5 6 7, if a = 3 then 2 4 5 6 7, if 2 then 5 7
here is my query
select *
from table
where a in (select b from table where a = 1) or a = 1
but the result only 3 2 4 6 because 3 has 2 in col b so i want also to have 5 7
thanks
I suspect that you have a hierarchical structure, where a is the parent and b is the child, and that you are looking for all descendents of a given node.
One common way to walk such structure is a hierarchical query. In SQL Server:
with cte as (
select a, b from mytable where a = #your_parameter
union all
select t.a, t.b from mytable t inner join cte c on t.a = c.b
)
select * from cte
Demo on DB Fiddle - when given 3 as parameter:
a | b
-: | -:
3 | 2
3 | 4
3 | 6
2 | 5
2 | 7

Adding a row number respecting the order of each row

I have a table like this
id, period, tag
1 1 A
1 2 A
1 3 B
1 4 A
1 5 A
1 6 A
2 1 A
2 2 B
2 3 B
2 4 B
2 5 B
2 6 A
I would like to add a new column with a ranking, respecting the order of the row given my column 'period' to obtain something like this
id, period, tag rank
1 1 A 1
1 2 A 1
1 3 B 2
1 4 A 3
1 5 A 3
1 6 A 3
2 1 A 1
2 2 B 2
2 3 B 2
2 4 B 2
2 5 B 2
2 6 A 3
What can I do?
I try rank and dense_rank function without any success
And another candidate for CONDITIONAL_CHANGE_EVENT()
less code, and quite effective, too ...!
WITH
input(id,period,tag) AS (
SELECT 1,1,'A'
UNION ALL SELECT 1,2,'A'
UNION ALL SELECT 1,3,'B'
UNION ALL SELECT 1,4,'A'
UNION ALL SELECT 1,5,'A'
UNION ALL SELECT 1,6,'A'
UNION ALL SELECT 2,1,'A'
UNION ALL SELECT 2,2,'B'
UNION ALL SELECT 2,3,'B'
UNION ALL SELECT 2,4,'B'
UNION ALL SELECT 2,5,'B'
UNION ALL SELECT 2,6,'A'
)
SELECT
*
, CONDITIONAL_CHANGE_EVENT(tag) OVER(PARTITION BY id ORDER BY period) + 1 AS rank
FROM input;
-- out id | period | tag | rank
-- out ----+--------+-----+------
-- out 1 | 1 | A | 1
-- out 1 | 2 | A | 1
-- out 1 | 3 | B | 2
-- out 1 | 4 | A | 3
-- out 1 | 5 | A | 3
-- out 1 | 6 | A | 3
-- out 2 | 1 | A | 1
-- out 2 | 2 | B | 2
-- out 2 | 3 | B | 2
-- out 2 | 4 | B | 2
-- out 2 | 5 | B | 2
-- out 2 | 6 | A | 3
-- out (12 rows)
-- out
-- out Time: First fetch (12 rows): 14.823 ms. All rows formatted: 14.874 ms
One method is a cumulative sum based on a lag():
select t.*,
sum(case when prev_tag = tag then 0 else 1 end) over (partition by id order by period) as rank
from (select t.*, lag(tag) over (partition by id order by period) as prev_tag
from t
) t;

How to get most common and least common value using sql?

Input table:
a b c
1 2 1
1 2 1
1 2 2
1 3 1
1 3 3
1 3 3
2 2 5
2 2 5
2 2 7
2 3 5
2 3 8
2 3 8
Expected output:
a b min max
1 2 2 1
1 3 1 3
2 2 7 5
2 3 5 8
Logic: Group by col a and col b, get the least common and most common values from col c.
In above example for a = 1 and b = 2, the least common value for col c is 2 and most common values for col c is 1, this is depicted in the first row of the output.
Currently i am able to count the occurence of each value by using the query
select a, b, c, count(c) from table group by a, b, c
Very late answer, but I find it interesting (and fun).
You have not tagged any specific rdbms but since most databases can use CTEs:
with
counters as (
select
a, b, c, count(*) counter
from tablename
group by a, b, c
),
minmax as (
select
a, b, min(counter) mincounter, max(counter) maxcounter
from counters
group by a, b
)
select
c.a, c.b,
max(case c.counter when m.mincounter then c.c end) min,
max(case c.counter when m.maxcounter then c.c end) max
from counters c inner join minmax m
on m.a = c.a and m.b = c.b and c.counter in (m.mincounter, m.maxcounter)
group by c.a, c.b
See the demo.
Results:
| a | b | min | max |
| --- | --- | --- | --- |
| 1 | 2 | 2 | 1 |
| 1 | 3 | 1 | 3 |
| 2 | 2 | 7 | 5 |
| 2 | 3 | 5 | 8 |

How to do it by simple sql or procedure

object_tbl:
objId(primary key) | name
1 | A
2 | B
3 | C
document_tbl:
documentId | sourceId
1 | 2
2 | 2
3 | 1
4 | 3
5 | 3
6 | 3
objToDoc_tbl:
id | objectId | documentId
1 | 1 | 2
2 | 2 | 4
3 | 2 | 6
4 | 1 | 5
5 | 3 | 1
6 | 1 | 2
Inner join of all table
A 2 2
B 4 3
B 6 3
A 5 3
C 1 2
A 2 2
A 2
B 1
C 1
so Answer is 1(As A is only 2)
Question: - How many object are related to documents from multiple sources.
How we can write sql query for this or it can only we solved by procedure
You can join all the tables and then use having to get objects with count > 1.
with t as (
select t.name, count(distinct d.sourceid) as count
from objtodoc_tbl o
join document_tbl d on o.documentid = d.documentid
join object_tbl t on o.objectid = t.name
group by t.name
having count(distinct d.sourceid) > 1
)
select count(t.name) from t;