shows blanks for repeating values in a result set
Wrap your existing query in CTE adding ROW_NUMBER OVER PARTITION BY
your columns, which will create RNs for each group of values. In outer query just use CASE to select values where GRP_RN = 1 and empty string otherwise.
WITH CTE AS
(
Select distinct top 100000
o.EventSetName,
o.EventSetDisplay,
o.EventSetDescription,
o.ChildSetName,
ROW_NUMBER() Over (Order By f.ChildSetName) RN,
f.DocumentDispSequence,
f.SectionDispSequence,
o.ObsSetDispSequence,
null as NullColumnNeedsName,
ROW_NUMBER() OVER (PARTITION BY o.EventSetName, o.EventSetDisplay,o.EventSetDescription ORDER BY f.ChildSetName) GRP_RN
From ##ObsSetLevel o,
INNER JOIN ##Final f ON f.ChildSetName = o.EventSetName and o.EventSetName = @variableName
)
SELECT
CASE WHEN GRP_RN = 1 THEN o.EventSetName ELSE '' END AS EventSetName,
CASE WHEN GRP_RN = 1 THEN o.EventSetDisplay ELSE '' END AS EventSetDisplay,
CASE WHEN GRP_RN = 1 THEN o.EventSetDescription ELSE '' END AS EventSetDescription,
other columns
FROM CTE
Order By RN asc, DocumentDispSequence asc, SectionDispSequence asc, o.ObsSetDispSequence asc
PS: I have also corrected your use of old-style joins. That usage is outdated more than 20 years ago with introduction of SQL-92 standards. You should avoid using them.
Duplicate data in unique rows, show blank instead
You can do what you want in the database. However, such presentation considerations are often better done at the application layer. Here is one method:
with bc as (
SELECT b.title AS Title, c.[Name] AS Char_Name, b.Plot_Summary AS Summary
FROM Books b INNER JOIN
Book_Char bc
ON b.id = bc.Book_id INNER JOIN
Characters c
ON c.id = bc.Char_id
)
select (case when seqnum = 1 then bc.title else '' end) as title, bc.Char_name,
(case when seqnum = 1 then bc.Summary else '' end) as Summary
from (select bc.*, row_number() over (partition by title order by char_name) as seqnum
from bc
) bc
order by bc.title, bc.char_name;
The real problem with your query, though, is that you are expecting results in a particular order. You only get results in a particular order (guaranteed) when you use order by
. And, your query has no order by
.
Replace duplicate values only in consecutive records with NULL
In both SQL Server and Oracle you can use LAG analytic function. Oracle:
WITH data (tran_id, tran_name, flag) AS (
SELECT 01, 'Lend', 'A' FROM DUAL UNION ALL
SELECT 101, 'Lend', 'B' FROM DUAL UNION ALL
SELECT 101, 'Lend', 'C' FROM DUAL UNION ALL
SELECT 101, 'Lend', 'D' FROM DUAL UNION ALL
SELECT 102, 'Borrow', 'E' FROM DUAL UNION ALL
SELECT 101, 'Lend', 'F' FROM DUAL UNION ALL
SELECT 101, 'Lend', 'G' FROM DUAL
)
SELECT
NVL2(keep, tran_id, null) tran_id,
NVL2(keep, tran_name, null) tran_name,
flag
FROM (
SELECT
tran_id, tran_name, flag,
CASE WHEN LAG(tran_id) OVER (ORDER BY flag) <> tran_id OR LAG(tran_name) OVER (ORDER BY flag) <> tran_name THEN 1 END keep
FROM
data)
How to make next repeated values as a blank if the value appears greater then 3 times
FWIW, here is another data.table
solution using rleid()
instead of duplicated()
.
Note that the OP requested to make next repeated values as a blank if the value appears greater then 3 times. This implies that for a Value
which is repeated exactly two times no blanks should appear in the result. I've amended my sample data set to include the case of exactly two repetitions of the same value.
Edit: The OP hasn't made it clear whether he is counting repetitions of the same Value
in the given sequence regardless of Name
or if he is counting repetitions in the sequence per Name
group. See also this comment.
In addition, the OP hasn't specified what result he expects if there's a sequence of repeated Value
s but with a change in Name
.
Therefore, I've modified my sample data set to include the additional use cases as well:
DT
# Name Value
# 1: A 24
# 2: A 24
# 3: A 45
# 4: A 45
# 5: A 45
# 6: A 45
# 7: A 45
# 8: A 93
# 9: A 19
#10: A 19
#11: A 10
#12: B 29
#13: B 67
#14: B 67
#15: B 67
#16: B 67
#17: C 201
#18: C 993
#19: C 396
#20: A 19
#21: A 19
#22: C 19
#23: B 29
#24: B 67
#25: B 67
#26: B 67
#27: B 67
#28: C 67
#29: C 67
#30: C 67
#31: C 67
# Name Value
As in the other answers, NA
is taken for blank.
library(data.table)
setDT(DT)[, New := Value[.N < 3], by=rleid(Value)][rowid(rleid(Value)) == 1L, New := Value]
DT
# Name Value New
# 1: A 24 24
# 2: A 24 24
# 3: A 45 45
# 4: A 45 NA
# 5: A 45 NA
# 6: A 45 NA
# 7: A 45 NA
# 8: A 93 93
# 9: A 19 19
#10: A 19 19
#11: A 10 10
#12: B 29 29
#13: B 67 67
#14: B 67 NA
#15: B 67 NA
#16: B 67 NA
#17: C 201 201
#18: C 993 993
#19: C 396 396
#20: A 19 19
#21: A 19 NA
#22: C 19 NA
#23: B 29 29
#24: B 67 67
#25: B 67 NA
#26: B 67 NA
#27: B 67 NA
#28: C 67 NA
#29: C 67 NA
#30: C 67 NA
#31: C 67 NA
# Name Value New
The first expression copies Value
for all RLE groups with one or two repetitions. All RLE groups with more repetitions get NA
. The second expressions copies Value
only for the first row in each RLE group.
Note that each sequence of repeated values is treated separately regardless of Name
but the change of A
to C
in row 22 and ofB
to C
in row 27 is being ignored.
This can be further improved to copy only if not already copied:
setDT(DT)[, New := Value[.N < 3], by=rleid(Value)
][is.na(New) & rowid(rleid(Value)) == 1L, New := Value]
In case the change in Name
is expected to "restart" Value
as well this variant could be used (credits to Jaap):
setDT(DT)[, New := Value[.N < 3], by = rleid(Name, Value)
][is.na(New) & rowid(rleid(Name, Value)) == 1L, New := Value][]
# Name Value New
# 1: A 24 24
# 2: A 24 24
# 3: A 45 45
# 4: A 45 NA
# 5: A 45 NA
# ...
#18: C 993 993
#19: C 396 396
#20: A 19 19
#21: A 19 19
#22: C 19 19
#23: B 29 29
#24: B 67 67
#25: B 67 NA
#26: B 67 NA
#27: B 67 NA
#28: C 67 67
#29: C 67 NA
#30: C 67 NA
#31: C 67 NA
# Name Value New
Note the difference in rows 21, 22, and 27.
Data
DT <- structure(list(Name = c("A", "A", "A", "A", "A", "A", "A", "A",
"A", "A", "A", "B", "B", "B", "B", "B", "C", "C", "C", "A", "A",
"C", "B", "B", "B", "B", "B", "C", "C", "C", "C"), Value = c(24L,
24L, 45L, 45L, 45L, 45L, 45L, 93L, 19L, 19L, 10L, 29L, 67L, 67L,
67L, 67L, 201L, 993L, 396L, 19L, 19L, 19L, 29L, 67L, 67L, 67L,
67L, 67L, 67L, 67L, 67L)), .Names = c("Name", "Value"), row.names = c(NA,
-31L), class = "data.frame")
Note that rows 1 and 8 have been duplicated w.r.t. the OP's data set to cover the case of exactly two repetitions and that a fews rows have been added at the end.
mysql select to return blanks for all but first row of repeating column
Yes, it's possible, but it would be very expensive (subqueries!) and not at all efficient. Whatever language you use or however you transfer this data directly, it's not worth it to have SQL spare these few bytes.
Related Topics
Can the "In" Operator Use Like-Wildcards (%) in Oracle
How to Change Date Format in Hive
How to List Field's Name in Table in Access Using SQL
Compare 3 Consecutive Rows in a Table
Increase Ms Access Insert Performance
SQL - Select Rows from Two Different Tables
Finding All Records Without Associated Ones
When Are Database Triggers Bad
Combining Union All and Order by in Firebird
Best to Use * When Calling a Lot of Fields in MySQL
Query Combinations with Nested Array of Records in JSON Datatype
How to Get a Value from Previous Result Row of a Select Statement