select query - eliminate rows with duplicate column value on condition - sql

I have a select query that ends up with results like:
ID COMPLIANT
------------------
10 0
12 0
29 0
29 1
43 1
44 1
44 0
How can I get results without these duplicate ID rows, on the condition that if an ID has already been marked as COMPLIANT once (a 1 instead of a 0), the duplicate rows with COMPLIANT=0 do not appear? I'd want:
ID COMPLIANT
------------------
10 0
12 0
29 1
43 1
44 1

How about aggregation?
select id, max(complaint) as complaint
from t
group by id;
This returns one row per id. If you can have multiple complaints -- and you want all of those -- than an alternative is:
select id, complaint
from t
where complaint = 1
union all
select id, complaint
from t
where not exists (select 1 from t t2 where t2.id = t.id and t2.complaint = 1);

this will work:
select id, max(complaint)
from tablename
group by id;

Related

how can i alternate between 0 and 1 values in sql server?

I want to create a select which will alternate between 1 and 0
my table looks like that
id1 id2 al
11 1 1
40 1 0
12 1 0
237 1 1
but I want to make it like that
id1 id2 al
40 1 0
11 1 1
12 1 0
237 1 1
I want to keep the same values in my table but I just want to switch the rows to alternate between 0 and 1
Consider:
select *
from mytable
order by row_number() over(partition by al order by id1), al
This alternates 0 and 1 values - if the groups have a different number of rows, then, once the smallest group exhausts, all remaining rows in the other group appear at the end of the resultset.
I am unsure which column you want to use to order the rows within each group - I assumed id1, but you might want to change that to your actual requirement.

Need to find the count of user who belongs to different depts

I have table with dept,user and so on, I need to find the number of count of user that belongs to different combinations of the dept.
Lets consider I've a table like this:
dept user
1 33
1 33
1 45
2 11
2 12
3 33
3 15
Then I've to find the uniq user and dept combination: something like this:
select distinct dept,user from x;
Which will give me result like :
Dept user
1 33
1 45
2 11
2 12
3 33
3 15
which actually removes the duplicates of the combination:
And here's the thing which i need to do :
My output should look like this:
dep_1_1 dep_1_2 dep_1_3 dep_2_2 dep_2_1 dep_2_3 Dep_3_1 Dep_3_2 Dep_3_3
2 0 1 2 0 0 1 0 2
So, Basically I need to find the count of common users between all the combinations of departments
Thanks for the help
You can get a row for each department combination using a self-join of your Distinct Select:
with cte as
(
select distinct dept,user from x
)
select t1.dept, t2.dept, count(*)
from cte a st1 join cte as t2
on t1.user = t2.user -- same user
and t1.dept < t2.dept -- different department
group by t1.dept, t2.dept
order by t1.dept, t2.dept

How to compare two rows in postgresql?

I have a table tab that contaions:
item identifier quantity methodid
10 1 20 2
10 1 30 3
11 1 10 3
11 1 12.5 3
11 2 20 5
12 1 20 1
12 1 30 1
I need to write a function that checks if there is a case of duplicate methodid for item and identifier.
In the above example item 11 identifier 1 has two rows of methodid 3 means it's duplicated, also item 12 idfentifier 1 has duplicated rows as well.
I don't need to do anything to the data just to identify this situation.
I don't need to find where and what was duplicated... just tell there is duplication.
The only information I have is the identifier
CREATE OR REPLACE FUNCTION func(identifier integer)
RETURNS integer AS
$BODY$
declare
errorcode int;
begin
if _____________ then
errorcode =1;
raise exception 'there id duplication in this identifier';
END IF;
continue work
return 0;
exception
when raise_exception then
return errorcode;
end;
$BODY$
LANGUAGE plpgsql VOLATILE
in the blank spot I want to put a query that checks for duplications.
How do I write a query that perform the check?
The structure of function can be changed. but I need somehow to know when to raise the exception.
To check wether any datasets are duplicated based on selected columns you could group by these columns and count the occurrences.
So in your case you could do:
SELECT 1 FROM tab GROUP BY item, identifier, methodid HAVING COUNT(*) > 1;
To incorporate this into your functions you could just check if it exists:
if EXISTS (SELECT 1 ...) then
Use group by:
select item, identifier, methodid, count(*)
from tab
group by item, identifier, methodid
having count(*) > 1
Where having count(*) > 1 is used to return only duplicated rows.
Try with this following one may be you will get your result set.
First generate a row number for the table which we have.
For that the following is the query.
select *,ROW_NUMBER() over (partition by item,identifier,methodid order by item) as RowID
from tab;
Then you will get the result like below.
Item Identifier quantity methodid RowID
10 1 20 2 1
10 1 30 3 1
11 1 10 3 1
11 1 12.5 3 2
11 2 20 5 1
12 1 20 1 1
12 1 30 1 2
12 1 40 2 1
So from this result set you can try with following query,then you will get the result
select * from (
select *,ROW_NUMBER() over (partition by item,identifier,methodid order by item) as rowid
from tab) as p
where p.rowid = 1
Thanks.
select *
from ( select item,identifier,quantity,methodid,
row_number() over(partition item,identifier,methodid) as rank)
each rank row with value higher than 1 is a duplicated row

How to declare a row as a Alternate Row

id Name claim priority
1 yatin 70 5
6 yatin 1 10
2 hiren 30 3
3 pankaj 40 2
4 kavin 50 1
5 jigo 10 4
7 jigo 1 10
this is my table and i want to arrange this table as shown below
id Name claim priority AlternateFlag
1 yatin 70 5 0
6 yatin 1 10 0
2 hiren 30 3 1
3 pankaj 40 2 0
4 kavin 50 1 1
5 jigo 10 4 0
7 jigo 1 10 0
It is sorted as alternate group of same row.
I am Using sql server 2005. Alternate flag starts with '0'. In my example First record with name "yatin" so set AlternateFlag as '0'.
Now second record has a same name as "yatin" so alternate flag would be '0'
Now Third record with name "hiren" is single record, so assign '1' to it
In short i want identify alternate group with same name...
Hope you understand my problem
Thanks in advance
Try
SELECT t.*, f.AlternateFlag
FROM tbl t
JOIN (
SELECT [name],
AlternateFlag = ~CAST(ROW_NUMBER() OVER(ORDER BY MIN(ID)) % 2 AS BIT)
FROM tbl
GROUP BY name
) f ON f.name = t.name
demo
You could use probably an aggregate function COUNT() and then HAVING() and then UNION both Table, like:
SELECT id, A.Name, Claim, Priority, 0 as AlternateFlag
FROM YourTable
INNER JOIN (
SELECT Name, COUNT(*) as NameCount
FROM YourTable
GROUP BY Name
HAVING COUNT(*) > 1 ) A
ON YourTable.Name = A.Name
UNION ALL
SELECT id, B.Name, Claim, Priority, 1 as AlternateFlag
FROM YourTable
INNER JOIN (
SELECT Name, COUNT(*) as NameCount
FROM YourTable
GROUP BY Name
HAVING COUNT(*) = 1 ) B
ON YourTable.Name = B.Name
Now, this assumes that the Names are unique meaning the names like Yatin for example although has two counts is only associated to one person.
See my SqlFiddle Demo
You can use Row_Number() function with OVER that will give you enumeration, than use the reminder of integer division it by 2 - so you'll get 1s and 0s in your SELECT or in the view.

Get record ids from groups where the sum of one of the field of their records is greater than

I have records as such:
Id ForeignKey Level ValueA ValueB
1 1001 1 2 10
2 1001 1 10 10
3 1001 1 20 20
4 1001 2 20 30
5 1002 1 1 100
6 1003 1 1 100
7 1004 1 1 100
I want to get the Ids of each record of the groups grouped by ForeignKey and Level where the sum of the group's records' ValueA values divided by the sum of ValueB values is greater than 0.5
In this case, I'd like to retrieve the Id of the three first records as (2 + 10 + 20) / (10 + 10 + 20) = 0.8
Here is what I've got so far:
select
ForeignKey,
SUM(ValueA) as ValueASum,
SUM(ValueB) as ValueBSum,
from tableA
group by ForeignKey
having (SUM(ValueA) / SUM(ValueB) > 0.5)
The result is
ForeignKey ValueASum ValueBSum
1001 32 40
How do I get the ids of the records from this point? If I add the Id in the select, I must group on it and then have a group for each record.
Thanks for your time
Hm, how about
select id from your_table where foreignkey = 1001
Is something wrong with working with multiple queries?
If you want you can do a subquery:
select id from your_table where foreignkey in ( select foreignkey from ( <yourQuery> ) sq);
UPDATE:
select t.id from Table1 t
inner join
(
select
ForeignKey, level,
SUM(ValueA) as ValueASum,
SUM(ValueB) as ValueBSum
from Table1
where level = 1
group by ForeignKey, Level
having (SUM(ValueA) / SUM(ValueB) > 0.5) ) sq
ON t.foreignkey = sq.foreignkey AND t.level = sq.level
I added where level = 1 just because your given resultset not what I get when I execute your query.
See it working live in an sqlfiddle.
You were on the right track, but if you wanted it from each "Level", you would need to add that into your group by also.
select
tA2.ID,
tA2.ForeignKey,
tA2.Level,
tA2.ValueA,
tA2.ValueB
from
( select
tA.ForeignKey,
tA.Level,
SUM(tA.ValueA) as ValueASum,
SUM(tA.ValueB) as ValueBSum,
from
tableA tA
group by
tA.ForeignKey,
tA.Level
having
(SUM(tA.ValueA) / SUM(tA.ValueB) > 0.5) ) PreQualified
JOIN tableA tA2
on PreQualified.ForeignKey = tA2.ForeignKey
AND PreQualified.Level = tA2.Level
This would give all values that matched the qualifying condition.