SQL Server SQL create substring to display the min and max date as a date range separated by a delimiter

cwdobuhd  于 2024-01-05  发布在  其他
关注(0)|答案(4)|浏览(96)

I have got this query (simplified from a detailed query) to return dates as a substring. I want to return a substring which has just the minimum and maximum of the date if more than 1 date else return just the one date.

This is my SQL query:

  1. SELECT
  2. SUBSTRING((SELECT distinct ','+ r.ENTRY AS [text()]
  3. FROM RESULT r
  4. WHERE r.ENTRY IN ('19-09-2023', '20-09-2023', '21-09-2023', '22-09-2023')
  5. AND r.sample_number = 74406
  6. FOR XML PATH (''), TYPE ).value('text()[1]', 'nvarchar(max)'), 2, 1000) [Test Date]

This query returns:

  1. 19-09-2023,20-09-2023,21-09-2023,22-09-2023

However, I want just 19/09-22/09/2023 to be returned i.e. min to max date in the above format. If there is only one date then I just want that date returned.

How do I amend the query to get this? I do need it as a substring since this is just one of many other columns returned.

I tried to add a CASE expression to get the min and max when there are more than 1 r.ENTRY . That didn't work. I do not have any more ideas.

Thanks

2w2cym1i

2w2cym1i1#

Since you are only interested in the minimum and maximum Date, you can use MIN() and MAX() together with CASE expression. No string aggregation is required

  1. select case when min(ENTRY) <> max(ENTRY)
  2. then convert(varchar(10), min(ENTRY), 105)
  3. + '-'
  4. + convert(varchar(10), max(ENTRY), 105)
  5. else convert(varchar(10), min(ENTRY), 105)
  6. end
  7. from RESULT r

CONVERT() with style 105 will return string in dd-mm-yyyy format.

igsr9ssn

igsr9ssn2#

Are you looking for consecutive values of the entry column for a specific value of the sample_number column?

  1. select @@version;
  2. With
  3. result as (
  4. select *
  5. from (
  6. values
  7. (cast('20230919' as date), 74406),
  8. ('20230920', 74406),
  9. ('20230921', 74406),
  10. ('20230922', 74406),
  11. ('20230923', 74407),
  12. ('20230925', 74408),
  13. ('20230929', 74408)
  14. ) as t(entry, sample_number)
  15. ),
  16. t1 as (
  17. select
  18. *,
  19. dateadd(day,
  20. -dense_rank() over(partition by sample_number
  21. order by entry),
  22. entry) as gr
  23. from result
  24. )
  25. select
  26. case
  27. when min(entry) = max(entry) then convert(nvarchar(10), min(entry), 103)
  28. else substring(convert(nvarchar(10), min(entry), 103), 1, 5) +
  29. '-' + convert(nvarchar(10), max(entry), 103)
  30. end as "Test Date"
  31. -- , sample_number
  32. from t1
  33. where
  34. sample_number = 74406 -- or 1 = 1
  35. group by gr -- , sample_number;

Results:

  1. +------------------+
  2. | Test Date |
  3. +------------------+
  4. | 19/09-22/09/2023 |
  5. +------------------+

DB Fiddle.

Results for all rows of test data:

  1. +------------------+---------------+
  2. | Test Date | sample_number |
  3. +------------------+---------------+
  4. | 19/09-22/09/2023 | 74406 |
  5. | 23/09/2023 | 74407 |
  6. | 25/09/2023 | 74408 |
  7. | 29/09/2023 | 74408 |
  8. +------------------+---------------+

DB Fiddle.

展开查看全部
brvekthn

brvekthn3#

A slightly more concise version of @Squirrel's excellent answer. You can use CONCAT_WS , which concatenates with a separator, and ignores nulls.

  1. select
  2. concat_ws('-',
  3. min(r.ENTRY),
  4. case when min(r.ENTRY) <> max(r.ENTRY) then convert(varchar(10), max(r.ENTRY), 105) end
  5. ) as [Test Date]
  6. from RESULT r;
hmtdttj4

hmtdttj44#

I have edited the suggested code to work for me. My field is not a date field so I had to use the replace and convert function to convert it to date and then the minimum and maximum works correctly. My working code as below:

  1. `SELECT
  2. SUBSTRING((SELECT distinct
  3. CASE when min(CONVERT(NVARCHAR(10),REPLACE(r.ENTRY,'-','/'),103)) = max(CONVERT(NVARCHAR(10),REPLACE(r.ENTRY,'-','/'),103)) THEN '-' + min(CONVERT(NVARCHAR(10),REPLACE(r.ENTRY,'-','/'),103)) ELSE
  4. '-' + min(CONVERT(NVARCHAR(10),REPLACE(r.ENTRY,'-','/'),103)) + ' - ' + max(CONVERT(NVARCHAR(10),REPLACE(r.ENTRY,'-','/'),103)) END AS [text()] FROM RESULT r
  5. WHERE r.ENTRY IN ('19-09-2023', '20-09-2023', '21-09-2023', '22-09-2023')
  6. AND r.sample_number = 74406
  7. FOR XML PATH (''), TYPE ).value('text()[1]', 'nvarchar(max)'), 2, 1000) [Test Date]`

相关问题