How to find rows that have one equal value and one different value from the table - sql

I have the following table:
ID Number Revision
x y 0
x y 1
z w 0
a w 0
a w 1
b m 0
b m 0
I need to return rows that for the same Number thare are more then one ID with the same Revision.Number can be "Null" and I don't need those values.
The output should be:
z w 0
a w 0
I have tried the following query:
SELECT a.id,a.number,a.revision,
FROM table a INNER JOIN
(SELECT id, number, revision FROM table where number > '0'
GROUP BY number HAVING COUNT(*) > 1
) b ON a.revision = b.revision AND a.id != b.id
A little addition- I have rows in my table with the same Number, ID and Revision- I don't need those rows in my query to be displayed!
It is not working! Please help me to figure out how to fix it.
Thanks.

Select t.Id,s.number,t.revision
from (Select number,count(*) 'c'
from table t1
where revision=0
group by number
having count(*) > 1
) s join table t on t.number= s.number
where revision = 0

Another simple approach:
SELECT DISTINCT b.id, b.Number, b.Revision
FROM tbl a
INNER JOIN tbl b
ON a.ID != b.ID AND a.Number = b.Number AND a.Revision = b.Revision;
This is tested in MySql 5, syntax might differ slightly.

You are not that far away with your query:
SELECT a.id,a.number,a.revision
FROM table a
JOIN (
-- multiple id for the same number and revision
SELECT number, revision
FROM table
GROUP BY number, revision
HAVING COUNT(*) > 1
) b
ON a.revision = b.revision
AND a.number = b.number
Untested, but you should get the idea. If your sql-server is a resent version you can solve this with OLAP functions as well.
To filter out rows where the whole row is duplicated we can select only unique rows via group by and having:
SELECT a.id,a.number,a.revision
FROM table a
JOIN (
-- multiple id for the same number and revision
SELECT number, revision
FROM table
GROUP BY number, revision
HAVING COUNT(*) > 1
) b
ON a.revision = b.revision
AND a.number = b.number
GROUP BY a.id,a.number,a.revision
HAVING COUNT(1) = 1

Related

Sql code for distinct fields

I was wondering if anyone can help me with this query.
I have two tables that I join together (DDS2ENVR.QBO AND KCA0001.ORTS)
THE QBO Table has a field labeled NIIN AND RIC. THE KCA0001.ORTS table has a field named SERVICE and OWN_RIC.
I Join the tables by QBO.RIC and ORTS.OWN_RIC. My dilemma is that under the NIIN field multiple rows can be identical but have different values for RIC.
Example:
NIIN RIC
123455 A
122222 B
123456 C
122222 A
I want to query a distinct count for NIINS that separates by the different service where it does not overlap. So example NIIN should only find distinct values only associated with A where the same NIIN is not found in B,C,D etc.
SELECT D.SERVICE, COUNT(C.NIIN)
FROM DDS2ENVR.QBO C
JOIN KCA0001.ORTS D ON D.OWN_RIC = C.RIC
WHERE C.SITE_ID = ('HEAA')
GROUP BY D.SERVICE
HAVING COUNT(DISTINCT C.NIIN) > 1
Please ask questions if this does not make any sense.
Using Not Exists
SELECT D.SERVICE, COUNT(C.NIIN)
FROM DDS2ENVR.QBO C
JOIN KCA0001.ORTS D ON D.OWN_RIC = C.RIC
WHERE C.SITE_ID = ('HEAA')
and NOT EXISTS (Select 1 from DDS2ENVR.QBO C1 where C1.NIIN = C.NIIN and C1.RIC <> C.RIC)
GROUP BY D.SERVICE
HAVING COUNT(DISTINCT C.NIIN) > 1
Also if the table DDS2ENVR.QBO doesn't contain duplicates and your dbms supports CTE
With cte as
(Select NIIN from DDS2ENVR.QBO group by NIIN having count(*) = 1)
SELECT D.SERVICE, COUNT(C.NIIN)
FROM DDS2ENVR.QBO C
JOIN KCA0001.ORTS D ON D.OWN_RIC = C.RIC
WHERE C.SITE_ID = ('HEAA')
and C.NIIN in (Select * from cte)
GROUP BY D.SERVICE
HAVING COUNT(DISTINCT C.NIIN) > 1

sql function case returns more than one row

Going to use this query as a subquery, the problem is it returns many rows of duplicates. Tried to use COUNT() instead of exists, but it still returns a multiple answer.
Every table can only contain one record of superRef.
The below query I`ll use in SELECT col_a, [the CASE] From MyTable
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = myTable.sysno AND A_specAttr = 'value')
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo WHERE C_superRef = myTable.sysno AND b_type = 2)
THEN 2
ELSE (SELECT C_intType FROM C
WHERE C_superRef = myTable.sysno)
END
FROM A, B, C
result:
3
3
3
3
3
3...
What if you did this? Because Im guessing you are getting an implicit full outer join A X B X C then running the case statement for each row in that result set.
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = 1000001838012)
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo AND C_superRef = 1000001838012 )
THEN 2
ELSE (SELECT C_type FROM C
WHERE C_superRef = 1000001838012)
END
FROM ( SELECT COUNT(*) FROM A ) --This is a hack but should work in ANSI sql.
--Your milage my vary with different RDBMS flavors.
DUAL is what I needed, thanks to Thorsten Kettner
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = 1000001838012)
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo AND C_superRef = 1000001838012 )
THEN 2
ELSE (SELECT C_type FROM C
WHERE C_superRef = 1000001838012)
END
FROM DUAL

Select one row that is a duplicate and also select the other rows that are not duplicates

here is my code
select i.RefNo,i.Premium,i.Description from (select d.Description,c.IsActiveRecord,c.RefNo,c.MovementID, c.Premium,ROW_NUMBER()
over(partition by c.premium order by c.refno) n from lif_mgm_t_contract c
inner join SDT_LJG_T_MovementDescription d with (nolock) on c.MovementID = d.MovementID ) i
where i.n = 1 and i.MovementID <> 0
so for instance
table
a
a
b
I want the query to return
a
b and not just a hope this makes sense --only a beginner
try using a group by clause
SELECT OrderNumber
FROM AccountOrder
group by OrderNumber
so if my table has the following order numbers
1
2
2
3
the query would return
1
2
3

Remove repeated values from the table

I have a PL/SQL select query like,
select
a.sgm,
b.numbr
from tbl1 a, tbl2 b
where b.itemId = a.itemId
and b.orgId = a.orgId
and a.srvCode = 'F'
and a.nbrCode <> 1
and rownum <= 7
Right now it retrieves like ,
sgm-|-numbr
-----------
abc-|-123
abc-|-678
abc-|-78
abc-|-099
bcd-|-153
bcd-|-123
bcd-|-123
I need to retrieve like ,
sgm-|-numbr
-----------
abc-|-123
bcd-|-153
ie, I need to remove the repeated ones in the first column. ie sgm shouldn't repeat.
Since you are using Oracle, then try this simplified version using a CTE:
WITH CTE as (
SELECT sgm, numbr,
rownum rn
FROM YourTable
)
SELECT CTE.sgm, CTE.numbr
FROM CTE
JOIN (
SELECT sgm, MIN(rownum) minrn
FROM CTE
GROUP BY sgm) t ON CTE.sgm = t.sgm AND CTE.rn = t.minrn
http://sqlfiddle.com/#!4/8d6fb/10
You can replace your query in the CTE above.
Good luck.
SELECT a.sgm, MAX(b.numbr)
FROM tbl1 a INNER JOIN tbl2 b
ON a.itemID = b.itemId
AND a.orgId = b.orgId
WHERE a.srvCode= 'F'
AND a.nbrCode <> 1
AND rownum <= 7
GROUP BY a.sgm
Apply a group function of your choice like MAX() on b.numbr, and apply the grouping on a.sgm, this should do what you need.
Advice : do your joins explicitly, see the difference between your query and mine.
select a.sgm,MAX(b.numbr)
from tbl1 a, tbl2 b
where b.itemId = a.itemId
AND b.orgId= a.orgId
and a.srvCode= 'F'
and a.nbrCode <> 1
and rownum<=7
group by sgm
The value of sgm wont repeat, but maximum value of number will be selected, similarly you can also select the minimum value using the Min function
Use group by function
select
a.sgm,
b.numbr
from tbl1 a, tbl2 b
where b.itemId = a.itemId
and b.orgId = a.orgId
and a.srvCode = 'F'
and a.nbrCode <> 1
and rownum <= 7
group by a.sgm
Select a from tbl a , tbl b WHERE a.userid > b..userid and
a.sgm = b.sgm;
Check this fiddle http://sqlfiddle.com/#!2/40b8f/2

Selecting max value from 2nd table in first table results

I have 2 tables as below-
Table I
ID DATE
1 05/11/12
2 23/11/12
3 29/11/12
4 04/10/12
5 20/11/12
And another table (IH) with the following info-
ID RECNO NOTE
1 1 Open
1 2 Update
1 3 Close
2 1 Open
2 2 Update
2 3 Hold
2 4 Close
3 1 Open
4 1 Open
4 2 Update
5 1 Open
I would like to output a result as shown below, displaying the Note field using the highest value of RecNo for each ID. So using the data above the output should be-
ID DATE NOTE
2 23/11/12 Close
3 29/11/12 Open
The code I have is-
SELECT I.ID, I.DATE, IH.NOTE FROM
I I, IH IH
JOIN (SELECT MAX([RECNO]) [RECNO] FROM
IH
GROUP BY RECNO) IH2 ON IH2.ID = IH.ID AND
IH2.[RECNO] = IH.[RECNO]
JOIN I I2 ON I2.ID = IH.ID WHERE
(I2.DATE>={TS ‘2012-11-22 00:00:002}) GROUP BY I2.ID
However when I execute the code I get-
Invalid Column Name 'RECNO'. Statement(s) could not be prepared.
How about this? Note, haven't tried it, I'm on my Mac at the moment.
SELECT I.ID, I.DATE, IH.NOTE
FROM I I
OUTER APPLY
(SELECT TOP 1 *
FROM IH
WHERE IH.ID = I.ID
ORDER BY RECNO DESC) IH
WHERE I.DATE >= '2012-11-22'
Your SQL is rather, uh, messy.
Assuming you are using SQL Server 2005 or greater, you can use the row_number() function, as follows:
SELECT I.ID, I.DATE, IH.NOTE
FROM I join
(select ih.*, ROW_NUMBER() over (PARTITION by id order by recno desc) as seqnum
from IH
) ih
on IH2.[RECNO] = IH.[RECNO] and seqnum = 1
WHERE I2.DATE>='2012-11-22 00:00:002'
This is assigning a sequence number in the IH table, for each id with the highest record number getting the value "1". The rest is just SQL.
Your original query is simply not correct syntactically, but I think this is what you want based on the description.
and another one
SELECT I.ID, I.DATE
,(Select TOP 1 IH.NOTE FROM IH where IH.ID=i.ID Order by Recno DESC) as Note
from I
WHERE
I.DATE>'20121122'
maybe this will help
SELECT a.ID, a.DATE, b.NOTE FROM a
inner join b on a.ID = b.ID
where b.recno in (select max(bb.recno)
from b as bb where bb.id = b.id)
http://sqlfiddle.com/#!3/fd141/2
If you don't mind the different identifiers, look at this solution:
select t1.MyID, t1.MyDate, y.Note
from t1
join
(
select MyID, max(RecNo) as RecNo
from t2
group by MyID
) x
on t1.MyID = x.MyID
left join
(
select *
from t2
) y
on t1.MyID = y.MyID
and x.RecNo = y.RecNo
where t1.MyDate >= '2012.11.22'
The complete solution is here: http://sqlfiddle.com/#!3/4ca09/3
Update: Oops, forgot to bring in the date in where clause. Updated SQL Fiddle and the query above.