T-SQL How to select rows without duplicate values from one column? - sql

I have a table with 2 columns ID, ID_PROJ_CSR
The content of that table is:
ID ID_PROJ_CSR
------------------
747 222 <
785 102
786 222 <
787 223
788 224
I want to select the ID, but if any value from ID_PROJ_CSR is a duplicate, I need to select any ID of the rows that contains that duplicate value (in that example, select ID 747 OR 786
I try:
SELECT * FROM my_table tab
WHERE tab.id_proj_csr = (SELECT TOP 1 id_proj_csr
FROM my_table mt
WHERE mt.id_proj_csr = tab.id_proj_csr)

You need to GROUP BY:
SELECT MAX(ID) as [ID], ID_PROJ_CSR
FROM my_table
GROUP BY ID_PROJ_CSR

Here's the case of omitting anything that has a duplicate value, so you'll only get rows that don't have duplicates:
SELECT *
FROM my_table
GROUP BY ID_PROJ_CSR
HAVING count(ID_PROJ_CSR) = 1;

Related

duplicate values in DB2

I am working on DB2.
There are duplicate rows in the table. I need to extract data where there is different value in 2nd column for same value in 1st column.
there are column other than these in table but only need to consider these.
for example:
NBR
SE_NBR
123
56
123
56
123
56
248
75
248
75
To extract
NBR
SE_NBR
456
12
456
34
456
11
135
77
135
88
here is one way using window function:
select * from
(
select *, min(SE_NBR) over (partition by NBR) minnbr, max(SE_NBR) over (partition by NBR) maxnbr
from nbrtable
) t
where minnbr <> maxnbr
if window function is not supported:
select * from tableName t1
where exists (
select 1 from tablename t2
where t1.NBR = t2.NBR
group by t2.nbr
having count(distinct SE_NBR) > 1
)
db<>fiddle here
You can do:
select *
from t
where nbr in (
select nbr from t group by nbr having count(distinct se_nbr) > 1
)

Select max value without group by [duplicate]

This question already has an answer here:
SQL Max(date) without group by
(1 answer)
Closed 2 years ago.
I need to help to get a max value for each id. Simple table is just shown below,
ID Value
---------------
111 150
112 110
111 100
113 120
115 130
111 180
112 190
What I want too see in the output:
ID Value
---------------
111 180
112 190
111 180
113 120
115 130
111 180
112 190
I do not want to group by each id, I want all of them in the output.
I think you want window functions:
select t.*, max(value) over (partition by id) as max_id
from t;
This answers the question. I'm not sure what the sample data has to do with the question.
You could also correlated subquery in the SELECT list:
SELECT
id,
(SELECT
max(value)
FROM
tbl t2
WHERE
t2.id = t1.id) AS value
FROM
tbl t1
If you do not want to use the MAX function at all then you can use the NOT EXISTS as follows:
SELECT Y.ID, R.VALUE
FROM YOUR_TABLE Y
JOIN ( SELECT DISTINCT ID, VALUE
FROM YOUR_TABLE T
WHERE NOT EXISTS ( SELECT 1
FROM YOUR_TABLE TT
WHERE TT.ID = T.ID
AND TT.VALUE > T.VALUE
)
) R ON Y.ID = R.ID

remove results from query if group is null

I have the below table:
Criteria:
Do not show results for grpid if there is a null custuserid for all grpid
grpid 145 should be seen as there is a custuserid on the second row.
Custid grpid custuserid date
101 145 12/30/19
101 145 dellf 1/1/20
101 255 dellf 1/1/20
201 456 1/1/20
201 555 smithr 1/1/20
output:
Custid grpid custuserid date
101 145 12/30/19
101 145 dellf 1/1/20
101 255 dellf 1/1/20
201 555 smithr 1/1/20
Best way to filter out these results?
I was thinking first_value could be used but is there a better way?
I would simpy use exists:
select t.*
from mytable t
where exists (
select 1 from mytable t1 where t1.grpid = t.grpid and t1.custuserid is not null
)
The correlated subquery ensures that at least one record with the same grpid has a non-null custuserid. For performance, you want an index on (grpid, custuserid).
You could also use window functions:
select *
from (
select t.*, max(custuserid) over(partition by grpid) max_custuserid
from mytable t
) t
where max_custuserid is not null
Or, you can join an aggregate query:
select t.*
from mytable t
inner join (
select
grpid,
max(custuserid)
from mytable
group by grpid
having max(custuserid) is not null
) x on x.grpid = t.grpid
Which option performs best would depend on your dataset (size, cardinality, ...).
Try below query
select * from temp1 where grpid not in (select grpid from temp1 group by grpid having count(custorid)=0)

SQL - Group dependant upon type

I've updated the question below as there's a little more complexity to it ...
A question relating to SQL grouping based on type?
I'd like to be able to list the max value for type-A (based on date - per CustID) whilst at the same time listing ALL values for type-b
From this :
Date Ref Type CustID
2019-03-04 123 A 1
2019-03-05 124 A 1
2019-03-06 125 B 3
2019-03-07 126 B 4
2019-03-08 127 B 5
2019-03-06 128 A 2
2019-03-07 129 A 2
2019-03-08 130 A 2
To this :
Date Ref Type CustID
2019-03-05 124 A 1
2019-03-06 125 B 3
2019-03-07 126 B 4
2019-03-08 127 B 5
2019-03-08 130 A 2
Thanks in advance :-)
Is this what you want?
with a as (
select top (1) t.*
from t
where type = 'A'
order by ref desc
)
select a.*
from a
union all
select t.*
from t
where type = 'B';
Or without union all:
select top (1) with ties t.*
from t
order by (case when type = 'B' then 1
else row_number() over (partition by type order by ref desc
end);
use union all
select date,ref,type from table where type='B'
union all
select date,ref,type from table where type='A'
and date = (select max(date) from table where type='A')
Try using union all
select top 1 date,ref, type from tablename
where Type='A' order by date desc
union all
select date,ref, type from tablename
where type='B'
The below query gives you type A records with latest date combined with B records
Select * from
( SELECT Date, Ref, Type
FROM TABLE
WHERE TYPE='A' GROUP BY TYPE
HAVING DATE =MAX(DATE)
UNION
SELECT Date, Ref, Type FROM TABLE
WHERE TYPE='B'
)

looping and union all in oracle select statement

I have the following table in oracle. version 9i
Num count
123 1
345 4
455 3
234 2
542 1
I am trying to write a select query which gives me the following output.
123
345
345
345
345
455
455
455
234
234
542
Each number should be displayed its count number of times. Can this be achieved if I use functions? I am not allowed to create any temporary tables.
I understand that I have to use loops sequences and then UNION ALL but not sure how to achieve it. I tried this
select Num from <table> where count=1
union all
// what fits here?
This could be done using pseudo column LEVEL and Correlated Query for repeating the num count number of times...
Try the below query
select num from (select distinct num,level,ROWID as RD
from table a
connect by level<= (select count from table b where a.num=b.num))
order by rd;
Try this
SELECT A.NUM
FROM Test A
INNER JOIN (SELECT ROWNUM RN FROM dual connect by level < 100) B
ON B.rn <= A.count
order by A.NUM;
SQL DEMO
WITH cte ("Num", "count")
AS
(
SELECT "Num", "count" FROM TableName
UNION ALL
SELECT "Num", "count" - 1 FROM cte WHERE "count" > 1
)
SELECT "Num"
FROM cte
ORDER BY "Num"
SQLFiddle Demo
If you're using 11gR2 you can do it like this:
with t(num, i) as
(
select num, count from tab1 union all
select num, i-1
from t
where i >1
)
select num from t
order by num;
Here is a sqlfiddle demo