Oracle, get all columns - oracle

I got this statement:
select count(*),
article_no_external,
article_group_id
from tbl_erp_article
where article_no_external != ' '
group by article_no_external, article_group_id
having count(*) >1
I want to group by group_id and external_no, this works just fine, I get 128 records. But I would like to see all columns not only those 2. I tried to add them to the select, but then I get an error with the group by. I need 4 more columns cause I need to grab them to make a new record using the selected data.

select article_no_external, article_group_id, col2, col3, col4, col5
from (
select article_no_external, article_group_id, col2, col3, col4, col,
count(*) over (partition by article_no_external, article_group_id) as cnt
from tbl_erp_article
where article_no_external <> ' '
)
where cnt > 1;
If you want to find non-empty varchar columns remember that Oracle doesn't have an empty string. An '' is converted to NULL during inserts or updates. So you probably want where article_no_external IS NOT NULL

You cant get all column values when you aggregate your fields for count, sum etc.
Not exacly same result but this may help you.
select *
from tbl_erp_article
where article_no_external != ' ' and
(article_no_external, article_group_id) in (
select article_no_external, article_group_id
from tbl_erp_article
where article_no_external != ' '
group by article_no_external, article_group_id
having count(*) >1)

Related

Fetch name based on comma-separated ids

I have two tables, customers and products.
products:
productid name
1 pro1
2 pro2
3 pro3
customers:
id name productid
1 cust1 1,2
2 cust2 1,3
3 cust3
i want following result in select statement,
id name productid
1 cust1 pro1,pro2
2 cust2 pro1,pro3
3 cust3
i have 300+ records in both tables, i am beginner to back end coding, any help?
Definitely a poor database design but the bad thing is that you have to live with that. Here is a solution which I created using recursive query. I don't see the use of product table though since your requirement has nothing to do with product table.
with
--Expanding each row seperated by comma
tab(col1,col2,col3) as (
Select distinct c.id,c.prdname,regexp_substr(c.productid,'[^,]',1,level)
from customers c
connect by regexp_substr(c.productid,'[^,]',1,level) is not null
order by 1),
--Appending `Pro` to each value
tab_final as ( Select col1,col2, case when col3 is not null
then 'pro'||col3
else col3
end col3
from tab )
--Displaying result as expected
SELECT
col1,
col2,
LISTAGG(col3,',') WITHIN GROUP( ORDER BY col1,col2 ) col3
FROM
tab_final
GROUP BY
col1,
col2
Demo:
--Preparing dataset
With
customers(id,prdname,productid) as ( Select 1, 'cust1', '1,2' from dual
UNION ALL
Select 2, 'cust2','1,3' from dual
UNION ALL
Select 3, 'cust3','' from dual),
--Expanding each row seperated by comma
tab(col1,col2,col3) as (
Select distinct c.id,c.prdname,regexp_substr(c.productid,'[^,]',1,level)
from customers c
connect by regexp_substr(c.productid,'[^,]',1,level) is not null
order by 1),
--Appending `Pro` to each value
tab_final as ( Select col1,col2, case when col3 is not null
then 'pro'||col3
else col3
end col3
from tab )
--Displaying result as expected
SELECT
col1,
col2,
LISTAGG(col3,',') WITHIN GROUP( ORDER BY col1,col2 ) col3
FROM
tab_final
GROUP BY
col1,
col2
PS: While using don't forget to put your actual table columns as in my example it may vary.

Hive Getting only max occurrence of a value

I have hive table which has two cloumns,I want to get the value which occured max number of times
For example in my below table a value occured twice and c only once , here a value is dominat so I want only a value as shown in output
col1 col2
a a_value1
a a_value2
a c_value3
b b_value1
OUTPUT:
col1 col2
a a_value1
b b_value1
You are looking for what statisticians call the mode. A pretty simple method is to use aggregation with a window function:
select col1, col2
from (select col1, col2, count(*) as cnt,
row_number() over (partition by col1 order by count(*) desc) as seqnum
from t
) t
where seqnum = 1;
The above query will return one value for each col1, even if there are ties. If you want all the values in the event of ties, then use rank() or dense_rank().

Change Default Hive result to some values

I was trying to get duplicate record count from table, but for particular partitions data is not available, so hive is only printing "OK" result.
Is it possible to change this result with some value like 0 Or NULL.
Yes have tried with nvl,COALESCE,case option still it showing OK. AND goal is to only check duplicate count, so required at least one value
select col1, col2, nvl(count(*),0) AS DUPLICATE_ROW_COUNT, 'xyz' AS TABLE_NAME
from xyz
where data_dt='20170423'
group by col1,col2
having count(*) >1
It will return no rows on empty dataset because you are using group by and having filter. Group by having nothing to group, that is why it does not return any rows. Without group by and having query returns 0:
select nvl(count(*),0) cnt, 'xyz' AS TABLE_NAME
from xyz
where data_dt='20170423'
As a solution you can UNION ALL with null row when empty dataset
select col1, col2, nvl(count(*),0) AS DUPLICATE_ROW_COUNT, 'xyz' AS TABLE_NAME
from xyz
where data_dt='20170423'
group by col1,col2
having count(*) >1
UNION ALL --returns 1 row on empty dataset
select col1, col2, DUPLICATE_ROW_COUNT, TABLE_NAME
from (select null col1, null col2, null AS DUPLICATE_ROW_COUNT, 'xyz' AS TABLE_NAME
)a --inner join will not return rows when non-empty dataset
inner join (
select count(*) cnt from --should will return 0 on empty dataset
( --your original query
select col1, col2, nvl(count(*),0) AS DUPLICATE_ROW_COUNT, 'xyz' AS TABLE_NAME
from xyz
where data_dt='20170423'
group by col1,col2
having count(*) >1
)s --your original query
)s on s.cnt=0
Also it's may be possible to use CTE (WITH) and WHERE NOT EXISTS instead of inner joinfor your subquery, didn't test it.
Also you can use shell to get result and test it on empty value:
dataset=$(hive -e "set hive.cli.print.header=false; [YOUR QUERY HERE]);
# test on empty dataset
if [[ -z "$dataset" ]] ; then
dataset=0
fi

Distinct in XMLAGG function in oracle sql

problem in avoiding duplicates using XMLAGG function
A table which is having multiple records. where each record has one column contains repetitive date.
Using XMLAGG function in the following sql
select col1, col2, XMLAGG(XMLELEMENT(E, colname || ',')).EXTRACT('//text()')
from table
group by col1, col2
i get the following output
col1 col2 col3
hareesh apartment residential, commercial, residential, residential
But i need the following output as
col3 : residential, commercial.
Anyone help me
Try using a subquery to remove duplicates:
SELECT col1, col2, XMLAGG(XMLELEMENT(E, colname || ',')).EXTRACT('//text()')
FROM (SELECT DISTINCT col1, col2, colname FROM table)
GROUP BY col1, col2

append string to varchar2 field based on the value of another field

Table 1 has
col1 varchar2(85)
col2 date
There is plenty of character space available in col1. If col2 value is previous to 2001, need to append to whatever value is in col1 the value OLD to the front end of whatever value may be in col1.
In some cases, col1 will be NULL. At most it will have values less than 40 characters in length.
Is there a SQL statement that can accomplish this without getting into PL/SQL?
Appreciate any and all help.
Something like the following should work:
select case when to_char(COL2, 'yyyy') < 2001
then 'OLD ' || nvl(COL1, '')
else COL1 end case
from TAB1
For example:
insert into TAB1 values ('testpost2001', trunc(sysdate));
insert into TAB1 values ('testpre2001', '01/Jul/2000');
insert into TAB1 values (null, trunc(sysdate));
insert into TAB1 values (null, '01/Jul/2000');
select COL1, COL2,
case when to_char(COL2, 'yyyy') < 2001
then 'OLD ' || nvl(COL1, '')
else COL1 end case
from TAB1;
Returns:
COL1 COL2 CASE
testpost2001 15/12/2011 testpost2001
testpre2001 1/07/2000 OLD testpre2001
15/12/2011
1/07/2000 OLD
This will also work in only one SQL statement as it will update all rows having value less than 2001...
update TAB1 set col1='OLD ' || nvl(COL1, '') where to_char(COL2, 'yyyy') < 2001;

Resources