Selecting one of the duplicate rows based on one column - sql

I've been trying to filter the duplicate rows out based on one column.
SELECT DISTINCT
a.id,
b.name,
b.number
FROM
b
LEFT JOIN a
ON a.name = b.name
ORDER BY
b.name
ASC;
And the result is:
id,name,number
1 Bob NULL
1 Bob 100
2 Bob NULL
2 Bob 200
3 Bob NULL
3 Bob 300
4 Bob 400
I'm trying to achieve the result like this:
id,name,number
1 Bob 100
2 Bob 200
3 Bob 300
4 Bob 400

If you want to combine the NULL values, I would suggest aggregation:
SELECT a.id, b.name, SUM(b.number) as number
FROM b LEFT JOIN
a
ON a.name = b.name
GROUP BY a.id, b.name;
Alternatively, just use a WHERE clause:
SELECT a.id, b.name, b.number
FROM b LEFT JOIN
a
ON a.name = b.name
WHERE b.name IS NOT NULL;

You can use ROW_NUMBER in order to selectively filter out NULL values in b.number field:
SELECT id, name, number
FROM (
SELECT a.id, b.name, b.number,
ROW_NUMBER() OVER (ORDER BY COALESCE(b.number, -1) DESC) AS rn
FROM b
LEFT JOIN a ON a.name = b.name) AS t
WHERE t.rn = 1
ORDER BY name ASC
The above query handles only cases with one, or at most two rows per id, with one of them, or both, being NULL.

Related

Select multiple count(*) in multiple tables with single query

I have 3 tables:
Basic
id
name
description
2
Name1
description2
3
Name2
description3
LinkA
id
linkA_ID
2
344
3
3221
2
6642
3
2312
2
323
LinkB
id
linkB_ID
2
8287
3
42466
2
616422
3
531
2
2555
2
8592
3
1122
2
33345
I want to get results as the table below:
id
name
description
linkA_count
linkB_count
2
Name1
description2
3
2
3
Name2
description3
5
3
my query:
SELECT
a.id
,a.name
,a.description
,COUNT(b.linkA_ID) AS linkA_count
,COUNT(c.linkB_ID) AS linkb_count
FROM
basic a
JOIN linkA b on (a.id = b.id)
JOIN linkb c on (a.id = c.id)
GROUP BY
a.id
,a.name
,a.description
Result from the query is count of linkA always same as linkB
A more traditional approach is to use "derived tables" (subqueries) so that the counts are performed before joins multiply the rows. Using left joins allows for all id's in basic to be returned by the query even if there are no related rows in either joined tables.
select
basic.id
, coalesce(a.LinkACount,0) LinkACount
, coalesce(b.linkBCount,0) linkBCount
from basic
left join (
select id, Count(linkA_ID) LinkACount from LinkA group by id
) as a on a.id=basic.id
left join (
select id, Count(linkB_ID) LinkBCount from LinkB group by id
) as b on b.id=basic.id
Try This (using SubQuery)
SELECT
basic.id
,basic.name
,basic.description
,(select Count(linkA_ID) from LinkA where LinkA.id=basic.id) as LinkACount
,(select Count(linkB_ID) from LinkB where LinkB.id=basic.id) as LinkBCount FROM basic
Method 2 (Try CTE)
with a as(select id,Count(linkA_ID)LinkACount from LinkA group by id)
, b as (select id,Count(linkB_ID)LinkBCount from LinkB group by id)
select basic.id,a.LinkACount,b.linkBCount
from basic
join a on (a.id=basic.id)
join b on (b.id=basic.id)
If you only select from your table you see why your query cannot work.
SELECT
*
FROM
basic a
JOIN linkA b on (a.id = b.id)
JOIN linkb c on (a.id = c.id)
WHERE a.ID = 3
=> just use distinct in your count
SELECT
a.id
,a.name
,a.description
,COUNT(DISTINCT(b.linkA_ID)) AS linkA_count
,COUNT(DISTINCT(c.linkB_ID)) AS linkb_count
FROM
basic a
JOIN linkA b on (a.id = b.id)
JOIN linkb c on (a.id = c.id)
GROUP BY
a.id
,a.name
,a.description

How to select rows by max value from another column in Oracle

I have two datasets in Oracle Table1 and Table2.
When I run this:
SELECT A.ID, B.NUM_X
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.ID=B.ID
WHERE B.BOOK = 1
It returns this.
ID NUM_X
1 10
1 5
1 9
2 2
2 1
3 20
3 11
What I want are the DISTINCT ID where NUM_X is the MAX value, something like this:
ID NUM_x
1 10
2 2
3 20
You can use aggregation:
SELECT A.ID, MAX(B.NUM_X)
FROM TABLE1 A LEFT JOIN
TABLE2 B
ON A.ID = B.ID
WHERE B.BOOK = 1
GROUP BY A.ID;
If you wanted additional columns, I would recommend window functions:
SELECT A.ID, MAX(B.NUM_X)
FROM TABLE1 A LEFT JOIN
(SELECT B.*,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY NUM_X DESC) as seqnum
FROM TABLE2 B
) B
ON A.ID = B.ID AND B.seqnum = 1
WHERE B.BOOK = 1
GROUP BY A.ID;

Group by the union of two columns

How can GROUP BY based on the union of two columns be achieved performantly? There may be NULL values in either column. Something like (obviously this doesn't work):
SELECT a.val, b.val
FROM a
LEFT JOIN b on a.id = b.id
GROUP BY UNION(a.val, b.val)
With results like:
a.val | b.val
-----------
1 1
2 2
NULL 3
4 NULL
5 5
Thanks!
Why can't you use NVL
SELECT NVL(a.val, b.val) FROM a LEFT JOIN b on a.id = b.id
GROUP BY NVL(a.val, b.val)

Count similar values from table by combining two tables

I have two table
table A
name id
ABC 1
PQR 2
XYZ 1
QWE 2
DFG 3
Another table
table B
id idname
1 stuart
2 bob
3 alex
expected output
id idname count
1 stuart 2
2 bob 2
3 alex 1
Iam using oracle 9i, Is it possible to obtain the expected result?
I have tried using distinct keyword but its not helping as it provides only the total count
That's simple. Join and count:
select b.id,
b.idname,
count(*) as cnt
from table_a a
join table_b b on a.id = b.id
group by b.id, b.idname;
If you need all the record from table b even if there is no corresponding row in table a, you can use an outer join:
select b.id,
b.idname,
count(a.id) as cnt
from table_a a
right join table_b b on a.id = b.id
group by b.id, b.idname;
Same can be achieved by using a left join:
select b.id,
b.idname,
count(a.id) as cnt
from table_b b
left join table_a a on a.id = b.id
group by b.id, b.idname;
Use JOIN to get data from both tables and use the aggregate function COUNT with GROUP BY.
Query
select t1.id, t1.idname, count(t2.name) as count
from TableB t1
left join TableA t2
on t1.id = t2.id
group by t1.id, t1.idname
order by count(t2.name) desc, t1.id;;

Different output when using count and group by

When trying to get a count of IDs I get a different answer when grouping by day vs when I am not.
select cv.CONV_DAY, count(distinct cv.CLICK_ID)
from
clickcache.click cc
right join(
select distinct cv.CLICK_ID, cv.CONV_DAY, cv.PIXEL_ID
from clickcache.CONVERSION cv
where cv.CLICK_ID IS NOT NULL) cv ON cv.CLICK_ID = cc.ID
where cc.ADV_ACCOUNT_ID = 25176
and cv.CONV_DAY between '2016-8-01' AND '2016-08-07'
and AMP_CLICK_STATUS_ID = 1
AND pixel_id IN
(SELECT DISTINCT conversion_pixel_id
FROM
ampx.campaign_event_funnel ef
JOIN ampx.campaign cp ON
cp.id = ef.campaign_id
AND cp.campaign_status_id = 1
WHERE
ef.account_id IN(25176)
AND include_optimization = 1 )
group by 1
order by 1 asc
This yields 170 which is the correct answer and the I want. This, on the other hand, displays 157.
select count(distinct cv.CLICK_ID)
from
clickcache.click cc
right join(
select distinct cv.CLICK_ID, cv.CONV_DAY, cv.PIXEL_ID
from clickcache.CONVERSION cv
where cv.CLICK_ID IS NOT NULL) cv ON cv.CLICK_ID = cc.ID
where cc.ADV_ACCOUNT_ID = 25176
and cv.CONV_DAY between '2016-8-01' AND '2016-08-07'
and AMP_CLICK_STATUS_ID = 1
AND pixel_id IN
(SELECT DISTINCT conversion_pixel_id
FROM
ampx.campaign_event_funnel ef
JOIN ampx.campaign cp ON
cp.id = ef.campaign_id
AND cp.campaign_status_id = 1
WHERE
ef.account_id IN(25176)
AND include_optimization = 1 )
My question is why do I get this discrepancy and how to fix it to get a proper count?
Thank you!
Your count dependents from right query, maybe you have duplicate row?
example
table1
id name value
1 2 3
table2
id name value
1 4 5
2 6 3
1 6 3
right join tables on value get result
select * from table1 a right join table2 b on a.value = b.value
1 2 3 2 6 3
1 2 3 1 6 3
select count(distinct a.value)
from (select a.id, a.name, a.value, b.id, b.name, b.value
from table1 a right join table2 b on a.value = b.value)
result is 1
select b.id, count(distinct a.value)
from (select a.id, a.name, a.value, b.id, b.name, b.value
from table1 a right join table2 b on a.value = b.value group)
group by b.id
result is two rows
2 1
1 1
My guess is that, you have a problem for this reason.